summaryrefslogtreecommitdiffstats
path: root/oss-fuzz
diff options
context:
space:
mode:
Diffstat (limited to 'oss-fuzz')
-rw-r--r--oss-fuzz/Makefile.am104
-rw-r--r--oss-fuzz/Makefile.in1033
-rw-r--r--oss-fuzz/Readme.md13
-rw-r--r--oss-fuzz/common.h2
-rw-r--r--oss-fuzz/decoder.cc408
-rw-r--r--oss-fuzz/empty.cc0
-rw-r--r--oss-fuzz/encoder.cc257
-rw-r--r--oss-fuzz/encoder_v2.cc352
-rw-r--r--oss-fuzz/fuzzer_encoder.dict18
-rw-r--r--oss-fuzz/fuzzing/datasource/datasource.hpp190
-rw-r--r--oss-fuzz/fuzzing/datasource/id.hpp75
-rw-r--r--oss-fuzz/fuzzing/exception.hpp67
-rw-r--r--oss-fuzz/fuzzing/memory.hpp96
-rw-r--r--oss-fuzz/fuzzing/types.hpp158
-rw-r--r--oss-fuzz/metadata.cc526
-rw-r--r--oss-fuzz/reencoder.cc304
-rw-r--r--oss-fuzz/seek.cc195
-rw-r--r--oss-fuzz/tool_flac.c117
-rw-r--r--oss-fuzz/tool_metaflac.c136
19 files changed, 4051 insertions, 0 deletions
diff --git a/oss-fuzz/Makefile.am b/oss-fuzz/Makefile.am
new file mode 100644
index 0000000..bf669aa
--- /dev/null
+++ b/oss-fuzz/Makefile.am
@@ -0,0 +1,104 @@
+# FLAC - Free Lossless Audio Codec
+# Copyright (C) 2019-2023 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_CFLAGS = ${LIB_FUZZING_ENGINE}
+AM_CXXFLAGS = -std=c++11 $(LIB_FUZZING_ENGINE)
+LDADD = $(flac_libs)
+
+
+EXTRA_DIST = \
+ fuzzer_encoder.dict \
+ common.h \
+ Readme.md \
+ fuzzing/datasource/datasource.hpp \
+ fuzzing/datasource/id.hpp \
+ fuzzing/exception.hpp \
+ fuzzing/memory.hpp \
+ fuzzing/types.hpp
+
+noinst_PROGRAMS =
+
+if USE_OSSFUZZERS
+noinst_PROGRAMS += fuzzer_encoder fuzzer_encoder_v2 fuzzer_decoder fuzzer_seek fuzzer_metadata fuzzer_reencoder fuzzer_tool_flac fuzzer_tool_metaflac
+endif
+
+fuzzer_encoder_SOURCES = encoder.cc
+fuzzer_encoder_v2_SOURCES = encoder_v2.cc
+fuzzer_decoder_SOURCES = decoder.cc
+fuzzer_seek_SOURCES = seek.cc
+fuzzer_metadata_SOURCES = metadata.cc
+fuzzer_reencoder_SOURCES = reencoder.cc
+fuzzer_tool_flac_SOURCES = ${flac_SOURCES} empty.cc tool_flac.c # empty.cc is to force use of C++ linker, which is mandated by oss-fuzz
+fuzzer_tool_flac_LDADD = \
+ $(top_builddir)/src/share/utf8/libutf8.la \
+ $(top_builddir)/src/share/grabbag/libgrabbag.la \
+ $(top_builddir)/src/share/getopt/libgetopt.la \
+ $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \
+ $(top_builddir)/src/share/replaygain_synthesis/libreplaygain_synthesis.la \
+ $(top_builddir)/src/libFLAC/libFLAC.la \
+ @LTLIBICONV@ \
+ -lm
+fuzzer_tool_metaflac_SOURCES = ${metaflac_SOURCES} empty.cc tool_metaflac.c # empty.cc is to force use of C++ linker, which is mandated by oss-fuzz
+fuzzer_tool_metaflac_LDADD = \
+ $(top_builddir)/src/share/utf8/libutf8.la \
+ $(top_builddir)/src/share/grabbag/libgrabbag.la \
+ $(top_builddir)/src/share/getopt/libgetopt.la \
+ $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \
+ $(top_builddir)/src/share/replaygain_synthesis/libreplaygain_synthesis.la \
+ $(top_builddir)/src/libFLAC/libFLAC.la \
+ @LTLIBICONV@ \
+ -lm
+
+flac_libs = \
+ $(top_builddir)/src/libFLAC/libFLAC-static.la \
+ $(top_builddir)/src/libFLAC++/libFLAC++-static.la \
+ @OGG_LIBS@ \
+ -lm
+
+flac_SOURCES = \
+ ${top_builddir}/src/flac/analyze.c \
+ ${top_builddir}/src/flac/decode.c \
+ ${top_builddir}/src/flac/encode.c \
+ ${top_builddir}/src/flac/foreign_metadata.c \
+ ${top_builddir}/src/flac/local_string_utils.c \
+ ${top_builddir}/src/flac/utils.c \
+ ${top_builddir}/src/flac/vorbiscomment.c \
+ ${top_builddir}/src/flac/analyze.h \
+ ${top_builddir}/src/flac/decode.h \
+ ${top_builddir}/src/flac/encode.h \
+ ${top_builddir}/src/flac/foreign_metadata.h \
+ ${top_builddir}/src/flac/local_string_utils.h \
+ ${top_builddir}/src/flac/utils.h \
+ ${top_builddir}/src/flac/vorbiscomment.h
+
+metaflac_SOURCES = \
+ ${top_builddir}/src/metaflac/operations.c \
+ ${top_builddir}/src/metaflac/operations_shorthand_cuesheet.c \
+ ${top_builddir}/src/metaflac/operations_shorthand_picture.c \
+ ${top_builddir}/src/metaflac/operations_shorthand_seektable.c \
+ ${top_builddir}/src/metaflac/operations_shorthand_streaminfo.c \
+ ${top_builddir}/src/metaflac/operations_shorthand_vorbiscomment.c \
+ ${top_builddir}/src/metaflac/options.c \
+ ${top_builddir}/src/metaflac/usage.c \
+ ${top_builddir}/src/metaflac/utils.c \
+ ${top_builddir}/src/metaflac/operations.h \
+ ${top_builddir}/src/metaflac/operations_shorthand.h \
+ ${top_builddir}/src/metaflac/options.h \
+ ${top_builddir}/src/metaflac/usage.h \
+ ${top_builddir}/src/metaflac/utils.h
diff --git a/oss-fuzz/Makefile.in b/oss-fuzz/Makefile.in
new file mode 100644
index 0000000..27620a4
--- /dev/null
+++ b/oss-fuzz/Makefile.in
@@ -0,0 +1,1033 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# FLAC - Free Lossless Audio Codec
+# Copyright (C) 2019-2023 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.
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = $(am__EXEEXT_1)
+@USE_OSSFUZZERS_TRUE@am__append_1 = fuzzer_encoder fuzzer_encoder_v2 fuzzer_decoder fuzzer_seek fuzzer_metadata fuzzer_reencoder fuzzer_tool_flac fuzzer_tool_metaflac
+subdir = oss-fuzz
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/add_cflags.m4 \
+ $(top_srcdir)/m4/add_cxxflags.m4 \
+ $(top_srcdir)/m4/ax_add_fortify_source.m4 \
+ $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_check_enable_debug.m4 \
+ $(top_srcdir)/m4/bswap.m4 $(top_srcdir)/m4/clang.m4 \
+ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gcc_version.m4 \
+ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/ogg.m4 \
+ $(top_srcdir)/m4/really_gcc.m4 \
+ $(top_srcdir)/m4/stack_protect.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+@USE_OSSFUZZERS_TRUE@am__EXEEXT_1 = fuzzer_encoder$(EXEEXT) \
+@USE_OSSFUZZERS_TRUE@ fuzzer_encoder_v2$(EXEEXT) \
+@USE_OSSFUZZERS_TRUE@ fuzzer_decoder$(EXEEXT) \
+@USE_OSSFUZZERS_TRUE@ fuzzer_seek$(EXEEXT) \
+@USE_OSSFUZZERS_TRUE@ fuzzer_metadata$(EXEEXT) \
+@USE_OSSFUZZERS_TRUE@ fuzzer_reencoder$(EXEEXT) \
+@USE_OSSFUZZERS_TRUE@ fuzzer_tool_flac$(EXEEXT) \
+@USE_OSSFUZZERS_TRUE@ fuzzer_tool_metaflac$(EXEEXT)
+PROGRAMS = $(noinst_PROGRAMS)
+am_fuzzer_decoder_OBJECTS = decoder.$(OBJEXT)
+fuzzer_decoder_OBJECTS = $(am_fuzzer_decoder_OBJECTS)
+fuzzer_decoder_LDADD = $(LDADD)
+am__DEPENDENCIES_1 = $(top_builddir)/src/libFLAC/libFLAC-static.la \
+ $(top_builddir)/src/libFLAC++/libFLAC++-static.la
+fuzzer_decoder_DEPENDENCIES = $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+am_fuzzer_encoder_OBJECTS = encoder.$(OBJEXT)
+fuzzer_encoder_OBJECTS = $(am_fuzzer_encoder_OBJECTS)
+fuzzer_encoder_LDADD = $(LDADD)
+fuzzer_encoder_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_fuzzer_encoder_v2_OBJECTS = encoder_v2.$(OBJEXT)
+fuzzer_encoder_v2_OBJECTS = $(am_fuzzer_encoder_v2_OBJECTS)
+fuzzer_encoder_v2_LDADD = $(LDADD)
+fuzzer_encoder_v2_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_fuzzer_metadata_OBJECTS = metadata.$(OBJEXT)
+fuzzer_metadata_OBJECTS = $(am_fuzzer_metadata_OBJECTS)
+fuzzer_metadata_LDADD = $(LDADD)
+fuzzer_metadata_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_fuzzer_reencoder_OBJECTS = reencoder.$(OBJEXT)
+fuzzer_reencoder_OBJECTS = $(am_fuzzer_reencoder_OBJECTS)
+fuzzer_reencoder_LDADD = $(LDADD)
+fuzzer_reencoder_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_fuzzer_seek_OBJECTS = seek.$(OBJEXT)
+fuzzer_seek_OBJECTS = $(am_fuzzer_seek_OBJECTS)
+fuzzer_seek_LDADD = $(LDADD)
+fuzzer_seek_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__dirstamp = $(am__leading_dot)dirstamp
+am__objects_1 = ${top_builddir}/src/flac/analyze.$(OBJEXT) \
+ ${top_builddir}/src/flac/decode.$(OBJEXT) \
+ ${top_builddir}/src/flac/encode.$(OBJEXT) \
+ ${top_builddir}/src/flac/foreign_metadata.$(OBJEXT) \
+ ${top_builddir}/src/flac/local_string_utils.$(OBJEXT) \
+ ${top_builddir}/src/flac/utils.$(OBJEXT) \
+ ${top_builddir}/src/flac/vorbiscomment.$(OBJEXT)
+am_fuzzer_tool_flac_OBJECTS = $(am__objects_1) empty.$(OBJEXT) \
+ tool_flac.$(OBJEXT)
+fuzzer_tool_flac_OBJECTS = $(am_fuzzer_tool_flac_OBJECTS)
+fuzzer_tool_flac_DEPENDENCIES = \
+ $(top_builddir)/src/share/utf8/libutf8.la \
+ $(top_builddir)/src/share/grabbag/libgrabbag.la \
+ $(top_builddir)/src/share/getopt/libgetopt.la \
+ $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \
+ $(top_builddir)/src/share/replaygain_synthesis/libreplaygain_synthesis.la \
+ $(top_builddir)/src/libFLAC/libFLAC.la
+am__objects_2 = ${top_builddir}/src/metaflac/operations.$(OBJEXT) \
+ ${top_builddir}/src/metaflac/operations_shorthand_cuesheet.$(OBJEXT) \
+ ${top_builddir}/src/metaflac/operations_shorthand_picture.$(OBJEXT) \
+ ${top_builddir}/src/metaflac/operations_shorthand_seektable.$(OBJEXT) \
+ ${top_builddir}/src/metaflac/operations_shorthand_streaminfo.$(OBJEXT) \
+ ${top_builddir}/src/metaflac/operations_shorthand_vorbiscomment.$(OBJEXT) \
+ ${top_builddir}/src/metaflac/options.$(OBJEXT) \
+ ${top_builddir}/src/metaflac/usage.$(OBJEXT) \
+ ${top_builddir}/src/metaflac/utils.$(OBJEXT)
+am_fuzzer_tool_metaflac_OBJECTS = $(am__objects_2) empty.$(OBJEXT) \
+ tool_metaflac.$(OBJEXT)
+fuzzer_tool_metaflac_OBJECTS = $(am_fuzzer_tool_metaflac_OBJECTS)
+fuzzer_tool_metaflac_DEPENDENCIES = \
+ $(top_builddir)/src/share/utf8/libutf8.la \
+ $(top_builddir)/src/share/grabbag/libgrabbag.la \
+ $(top_builddir)/src/share/getopt/libgetopt.la \
+ $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \
+ $(top_builddir)/src/share/replaygain_synthesis/libreplaygain_synthesis.la \
+ $(top_builddir)/src/libFLAC/libFLAC.la
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ${top_builddir}/src/flac/$(DEPDIR)/analyze.Po \
+ ${top_builddir}/src/flac/$(DEPDIR)/decode.Po \
+ ${top_builddir}/src/flac/$(DEPDIR)/encode.Po \
+ ${top_builddir}/src/flac/$(DEPDIR)/foreign_metadata.Po \
+ ${top_builddir}/src/flac/$(DEPDIR)/local_string_utils.Po \
+ ${top_builddir}/src/flac/$(DEPDIR)/utils.Po \
+ ${top_builddir}/src/flac/$(DEPDIR)/vorbiscomment.Po \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/operations.Po \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_cuesheet.Po \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_picture.Po \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_seektable.Po \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_streaminfo.Po \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_vorbiscomment.Po \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/options.Po \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/usage.Po \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/utils.Po \
+ ./$(DEPDIR)/decoder.Po ./$(DEPDIR)/empty.Po \
+ ./$(DEPDIR)/encoder.Po ./$(DEPDIR)/encoder_v2.Po \
+ ./$(DEPDIR)/metadata.Po ./$(DEPDIR)/reencoder.Po \
+ ./$(DEPDIR)/seek.Po ./$(DEPDIR)/tool_flac.Po \
+ ./$(DEPDIR)/tool_metaflac.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+SOURCES = $(fuzzer_decoder_SOURCES) $(fuzzer_encoder_SOURCES) \
+ $(fuzzer_encoder_v2_SOURCES) $(fuzzer_metadata_SOURCES) \
+ $(fuzzer_reencoder_SOURCES) $(fuzzer_seek_SOURCES) \
+ $(fuzzer_tool_flac_SOURCES) $(fuzzer_tool_metaflac_SOURCES)
+DIST_SOURCES = $(fuzzer_decoder_SOURCES) $(fuzzer_encoder_SOURCES) \
+ $(fuzzer_encoder_v2_SOURCES) $(fuzzer_metadata_SOURCES) \
+ $(fuzzer_reencoder_SOURCES) $(fuzzer_seek_SOURCES) \
+ $(fuzzer_tool_flac_SOURCES) $(fuzzer_tool_metaflac_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLE_64_BIT_WORDS = @ENABLE_64_BIT_WORDS@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FLAC__HAS_OGG = @FLAC__HAS_OGG@
+FLAC__TEST_LEVEL = @FLAC__TEST_LEVEL@
+FLAC__TEST_WITH_VALGRIND = @FLAC__TEST_WITH_VALGRIND@
+GCC_MAJOR_VERSION = @GCC_MAJOR_VERSION@
+GCC_MINOR_VERSION = @GCC_MINOR_VERSION@
+GCC_VERSION = @GCC_VERSION@
+GIT_COMMIT_VERSION_HASH = @GIT_COMMIT_VERSION_HASH@
+GIT_FOUND = @GIT_FOUND@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
+LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OBJ_FORMAT = @OBJ_FORMAT@
+OGG_CFLAGS = @OGG_CFLAGS@
+OGG_LIBS = @OGG_LIBS@
+OGG_PACKAGE = @OGG_PACKAGE@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PANDOC = @PANDOC@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/oss-fuzz
+AM_CFLAGS = ${LIB_FUZZING_ENGINE}
+AM_CXXFLAGS = -std=c++11 $(LIB_FUZZING_ENGINE)
+LDADD = $(flac_libs)
+EXTRA_DIST = \
+ fuzzer_encoder.dict \
+ common.h \
+ Readme.md \
+ fuzzing/datasource/datasource.hpp \
+ fuzzing/datasource/id.hpp \
+ fuzzing/exception.hpp \
+ fuzzing/memory.hpp \
+ fuzzing/types.hpp
+
+fuzzer_encoder_SOURCES = encoder.cc
+fuzzer_encoder_v2_SOURCES = encoder_v2.cc
+fuzzer_decoder_SOURCES = decoder.cc
+fuzzer_seek_SOURCES = seek.cc
+fuzzer_metadata_SOURCES = metadata.cc
+fuzzer_reencoder_SOURCES = reencoder.cc
+fuzzer_tool_flac_SOURCES = ${flac_SOURCES} empty.cc tool_flac.c # empty.cc is to force use of C++ linker, which is mandated by oss-fuzz
+fuzzer_tool_flac_LDADD = \
+ $(top_builddir)/src/share/utf8/libutf8.la \
+ $(top_builddir)/src/share/grabbag/libgrabbag.la \
+ $(top_builddir)/src/share/getopt/libgetopt.la \
+ $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \
+ $(top_builddir)/src/share/replaygain_synthesis/libreplaygain_synthesis.la \
+ $(top_builddir)/src/libFLAC/libFLAC.la \
+ @LTLIBICONV@ \
+ -lm
+
+fuzzer_tool_metaflac_SOURCES = ${metaflac_SOURCES} empty.cc tool_metaflac.c # empty.cc is to force use of C++ linker, which is mandated by oss-fuzz
+fuzzer_tool_metaflac_LDADD = \
+ $(top_builddir)/src/share/utf8/libutf8.la \
+ $(top_builddir)/src/share/grabbag/libgrabbag.la \
+ $(top_builddir)/src/share/getopt/libgetopt.la \
+ $(top_builddir)/src/share/replaygain_analysis/libreplaygain_analysis.la \
+ $(top_builddir)/src/share/replaygain_synthesis/libreplaygain_synthesis.la \
+ $(top_builddir)/src/libFLAC/libFLAC.la \
+ @LTLIBICONV@ \
+ -lm
+
+flac_libs = \
+ $(top_builddir)/src/libFLAC/libFLAC-static.la \
+ $(top_builddir)/src/libFLAC++/libFLAC++-static.la \
+ @OGG_LIBS@ \
+ -lm
+
+flac_SOURCES = \
+ ${top_builddir}/src/flac/analyze.c \
+ ${top_builddir}/src/flac/decode.c \
+ ${top_builddir}/src/flac/encode.c \
+ ${top_builddir}/src/flac/foreign_metadata.c \
+ ${top_builddir}/src/flac/local_string_utils.c \
+ ${top_builddir}/src/flac/utils.c \
+ ${top_builddir}/src/flac/vorbiscomment.c \
+ ${top_builddir}/src/flac/analyze.h \
+ ${top_builddir}/src/flac/decode.h \
+ ${top_builddir}/src/flac/encode.h \
+ ${top_builddir}/src/flac/foreign_metadata.h \
+ ${top_builddir}/src/flac/local_string_utils.h \
+ ${top_builddir}/src/flac/utils.h \
+ ${top_builddir}/src/flac/vorbiscomment.h
+
+metaflac_SOURCES = \
+ ${top_builddir}/src/metaflac/operations.c \
+ ${top_builddir}/src/metaflac/operations_shorthand_cuesheet.c \
+ ${top_builddir}/src/metaflac/operations_shorthand_picture.c \
+ ${top_builddir}/src/metaflac/operations_shorthand_seektable.c \
+ ${top_builddir}/src/metaflac/operations_shorthand_streaminfo.c \
+ ${top_builddir}/src/metaflac/operations_shorthand_vorbiscomment.c \
+ ${top_builddir}/src/metaflac/options.c \
+ ${top_builddir}/src/metaflac/usage.c \
+ ${top_builddir}/src/metaflac/utils.c \
+ ${top_builddir}/src/metaflac/operations.h \
+ ${top_builddir}/src/metaflac/operations_shorthand.h \
+ ${top_builddir}/src/metaflac/options.h \
+ ${top_builddir}/src/metaflac/usage.h \
+ ${top_builddir}/src/metaflac/utils.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign oss-fuzz/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign oss-fuzz/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+fuzzer_decoder$(EXEEXT): $(fuzzer_decoder_OBJECTS) $(fuzzer_decoder_DEPENDENCIES) $(EXTRA_fuzzer_decoder_DEPENDENCIES)
+ @rm -f fuzzer_decoder$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(fuzzer_decoder_OBJECTS) $(fuzzer_decoder_LDADD) $(LIBS)
+
+fuzzer_encoder$(EXEEXT): $(fuzzer_encoder_OBJECTS) $(fuzzer_encoder_DEPENDENCIES) $(EXTRA_fuzzer_encoder_DEPENDENCIES)
+ @rm -f fuzzer_encoder$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(fuzzer_encoder_OBJECTS) $(fuzzer_encoder_LDADD) $(LIBS)
+
+fuzzer_encoder_v2$(EXEEXT): $(fuzzer_encoder_v2_OBJECTS) $(fuzzer_encoder_v2_DEPENDENCIES) $(EXTRA_fuzzer_encoder_v2_DEPENDENCIES)
+ @rm -f fuzzer_encoder_v2$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(fuzzer_encoder_v2_OBJECTS) $(fuzzer_encoder_v2_LDADD) $(LIBS)
+
+fuzzer_metadata$(EXEEXT): $(fuzzer_metadata_OBJECTS) $(fuzzer_metadata_DEPENDENCIES) $(EXTRA_fuzzer_metadata_DEPENDENCIES)
+ @rm -f fuzzer_metadata$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(fuzzer_metadata_OBJECTS) $(fuzzer_metadata_LDADD) $(LIBS)
+
+fuzzer_reencoder$(EXEEXT): $(fuzzer_reencoder_OBJECTS) $(fuzzer_reencoder_DEPENDENCIES) $(EXTRA_fuzzer_reencoder_DEPENDENCIES)
+ @rm -f fuzzer_reencoder$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(fuzzer_reencoder_OBJECTS) $(fuzzer_reencoder_LDADD) $(LIBS)
+
+fuzzer_seek$(EXEEXT): $(fuzzer_seek_OBJECTS) $(fuzzer_seek_DEPENDENCIES) $(EXTRA_fuzzer_seek_DEPENDENCIES)
+ @rm -f fuzzer_seek$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(fuzzer_seek_OBJECTS) $(fuzzer_seek_LDADD) $(LIBS)
+${top_builddir}/src/flac/$(am__dirstamp):
+ @$(MKDIR_P) ${top_builddir}/src/flac
+ @: > ${top_builddir}/src/flac/$(am__dirstamp)
+${top_builddir}/src/flac/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) ${top_builddir}/src/flac/$(DEPDIR)
+ @: > ${top_builddir}/src/flac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/flac/analyze.$(OBJEXT): \
+ ${top_builddir}/src/flac/$(am__dirstamp) \
+ ${top_builddir}/src/flac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/flac/decode.$(OBJEXT): \
+ ${top_builddir}/src/flac/$(am__dirstamp) \
+ ${top_builddir}/src/flac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/flac/encode.$(OBJEXT): \
+ ${top_builddir}/src/flac/$(am__dirstamp) \
+ ${top_builddir}/src/flac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/flac/foreign_metadata.$(OBJEXT): \
+ ${top_builddir}/src/flac/$(am__dirstamp) \
+ ${top_builddir}/src/flac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/flac/local_string_utils.$(OBJEXT): \
+ ${top_builddir}/src/flac/$(am__dirstamp) \
+ ${top_builddir}/src/flac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/flac/utils.$(OBJEXT): \
+ ${top_builddir}/src/flac/$(am__dirstamp) \
+ ${top_builddir}/src/flac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/flac/vorbiscomment.$(OBJEXT): \
+ ${top_builddir}/src/flac/$(am__dirstamp) \
+ ${top_builddir}/src/flac/$(DEPDIR)/$(am__dirstamp)
+
+fuzzer_tool_flac$(EXEEXT): $(fuzzer_tool_flac_OBJECTS) $(fuzzer_tool_flac_DEPENDENCIES) $(EXTRA_fuzzer_tool_flac_DEPENDENCIES)
+ @rm -f fuzzer_tool_flac$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(fuzzer_tool_flac_OBJECTS) $(fuzzer_tool_flac_LDADD) $(LIBS)
+${top_builddir}/src/metaflac/$(am__dirstamp):
+ @$(MKDIR_P) ${top_builddir}/src/metaflac
+ @: > ${top_builddir}/src/metaflac/$(am__dirstamp)
+${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) ${top_builddir}/src/metaflac/$(DEPDIR)
+ @: > ${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/metaflac/operations.$(OBJEXT): \
+ ${top_builddir}/src/metaflac/$(am__dirstamp) \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/metaflac/operations_shorthand_cuesheet.$(OBJEXT): \
+ ${top_builddir}/src/metaflac/$(am__dirstamp) \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/metaflac/operations_shorthand_picture.$(OBJEXT): \
+ ${top_builddir}/src/metaflac/$(am__dirstamp) \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/metaflac/operations_shorthand_seektable.$(OBJEXT): \
+ ${top_builddir}/src/metaflac/$(am__dirstamp) \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/metaflac/operations_shorthand_streaminfo.$(OBJEXT): \
+ ${top_builddir}/src/metaflac/$(am__dirstamp) \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/metaflac/operations_shorthand_vorbiscomment.$(OBJEXT): \
+ ${top_builddir}/src/metaflac/$(am__dirstamp) \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/metaflac/options.$(OBJEXT): \
+ ${top_builddir}/src/metaflac/$(am__dirstamp) \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/metaflac/usage.$(OBJEXT): \
+ ${top_builddir}/src/metaflac/$(am__dirstamp) \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp)
+${top_builddir}/src/metaflac/utils.$(OBJEXT): \
+ ${top_builddir}/src/metaflac/$(am__dirstamp) \
+ ${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp)
+
+fuzzer_tool_metaflac$(EXEEXT): $(fuzzer_tool_metaflac_OBJECTS) $(fuzzer_tool_metaflac_DEPENDENCIES) $(EXTRA_fuzzer_tool_metaflac_DEPENDENCIES)
+ @rm -f fuzzer_tool_metaflac$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(fuzzer_tool_metaflac_OBJECTS) $(fuzzer_tool_metaflac_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f ${top_builddir}/src/flac/*.$(OBJEXT)
+ -rm -f ${top_builddir}/src/metaflac/*.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/flac/$(DEPDIR)/analyze.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/flac/$(DEPDIR)/decode.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/flac/$(DEPDIR)/encode.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/flac/$(DEPDIR)/foreign_metadata.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/flac/$(DEPDIR)/local_string_utils.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/flac/$(DEPDIR)/utils.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/flac/$(DEPDIR)/vorbiscomment.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/metaflac/$(DEPDIR)/operations.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_cuesheet.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_picture.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_seektable.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_streaminfo.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_vorbiscomment.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/metaflac/$(DEPDIR)/options.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/metaflac/$(DEPDIR)/usage.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@${top_builddir}/src/metaflac/$(DEPDIR)/utils.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decoder.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/empty.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoder.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoder_v2.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/metadata.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reencoder.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/seek.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tool_flac.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tool_metaflac.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+.cc.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/$(am__dirstamp)
+ -rm -f ${top_builddir}/src/flac/$(am__dirstamp)
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/$(am__dirstamp)
+ -rm -f ${top_builddir}/src/metaflac/$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/analyze.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/decode.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/encode.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/foreign_metadata.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/local_string_utils.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/utils.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/vorbiscomment.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_cuesheet.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_picture.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_seektable.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_streaminfo.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_vorbiscomment.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/options.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/usage.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/utils.Po
+ -rm -f ./$(DEPDIR)/decoder.Po
+ -rm -f ./$(DEPDIR)/empty.Po
+ -rm -f ./$(DEPDIR)/encoder.Po
+ -rm -f ./$(DEPDIR)/encoder_v2.Po
+ -rm -f ./$(DEPDIR)/metadata.Po
+ -rm -f ./$(DEPDIR)/reencoder.Po
+ -rm -f ./$(DEPDIR)/seek.Po
+ -rm -f ./$(DEPDIR)/tool_flac.Po
+ -rm -f ./$(DEPDIR)/tool_metaflac.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/analyze.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/decode.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/encode.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/foreign_metadata.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/local_string_utils.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/utils.Po
+ -rm -f ${top_builddir}/src/flac/$(DEPDIR)/vorbiscomment.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_cuesheet.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_picture.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_seektable.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_streaminfo.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/operations_shorthand_vorbiscomment.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/options.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/usage.Po
+ -rm -f ${top_builddir}/src/metaflac/$(DEPDIR)/utils.Po
+ -rm -f ./$(DEPDIR)/decoder.Po
+ -rm -f ./$(DEPDIR)/empty.Po
+ -rm -f ./$(DEPDIR)/encoder.Po
+ -rm -f ./$(DEPDIR)/encoder_v2.Po
+ -rm -f ./$(DEPDIR)/metadata.Po
+ -rm -f ./$(DEPDIR)/reencoder.Po
+ -rm -f ./$(DEPDIR)/seek.Po
+ -rm -f ./$(DEPDIR)/tool_flac.Po
+ -rm -f ./$(DEPDIR)/tool_metaflac.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/oss-fuzz/Readme.md b/oss-fuzz/Readme.md
new file mode 100644
index 0000000..90f2763
--- /dev/null
+++ b/oss-fuzz/Readme.md
@@ -0,0 +1,13 @@
+Fuzzers fuzzer_decoder.cc and fuzzer_encoder.cc were taken from
+
+ https://github.com/guidovranken/flac-fuzzers
+
+The header files in the directory fuzzing and below were taken from:
+
+ https://github.com/guidovranken/fuzzing-headers.git
+
+Some minor modifications were made to make them build with the default C++
+warning flags.
+
+The code mentioned above, contributed by Guido Vranken, is licensed under
+the MIT license. See the files themselves for details
diff --git a/oss-fuzz/common.h b/oss-fuzz/common.h
new file mode 100644
index 0000000..9545f95
--- /dev/null
+++ b/oss-fuzz/common.h
@@ -0,0 +1,2 @@
+extern int alloc_check_threshold, alloc_check_counter;
+int alloc_check_threshold = INT32_MAX, alloc_check_counter = 0;
diff --git a/oss-fuzz/decoder.cc b/oss-fuzz/decoder.cc
new file mode 100644
index 0000000..b7ddf21
--- /dev/null
+++ b/oss-fuzz/decoder.cc
@@ -0,0 +1,408 @@
+/* Copyright 2019 Guido Vranken
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <cstddef>
+#include <cstdint>
+
+#include <fuzzing/datasource/datasource.hpp>
+#include <fuzzing/memory.hpp>
+
+#include "FLAC++/decoder.h"
+#include "FLAC++/metadata.h"
+#include "common.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 {
+ Metadata::Prototype * cloned_object = nullptr;
+ 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);
+ if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
+ cloned_object = new Metadata::StreamInfo(metadata);
+ else if (metadata->type == FLAC__METADATA_TYPE_PADDING)
+ cloned_object = new Metadata::Padding(metadata);
+ else if (metadata->type == FLAC__METADATA_TYPE_APPLICATION)
+ cloned_object = new Metadata::Application(metadata);
+ else if (metadata->type == FLAC__METADATA_TYPE_SEEKTABLE)
+ cloned_object = new Metadata::SeekTable(metadata);
+ else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
+ cloned_object = new Metadata::VorbisComment(metadata);
+ else if (metadata->type == FLAC__METADATA_TYPE_CUESHEET)
+ cloned_object = new Metadata::CueSheet(metadata);
+ else if (metadata->type == FLAC__METADATA_TYPE_PICTURE)
+ cloned_object = new Metadata::Picture(metadata);
+ else
+ return;
+ if (0 != cloned_object && *cloned_object == *metadata && cloned_object->is_valid()) {
+ if (cloned_object->get_type() == FLAC__METADATA_TYPE_SEEKTABLE)
+ dynamic_cast<Metadata::SeekTable *>(cloned_object)->is_legal();
+ if (cloned_object->get_type() == FLAC__METADATA_TYPE_PICTURE)
+ dynamic_cast<Metadata::Picture *>(cloned_object)->is_legal(NULL);
+ if (cloned_object->get_type() == FLAC__METADATA_TYPE_CUESHEET)
+ dynamic_cast<Metadata::CueSheet *>(cloned_object)->is_legal(true,NULL);
+ }
+ delete cloned_object;
+ }
+
+ ::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);
+ bool use_ogg = true;
+
+ try {
+ if ( ds.Get<bool>() ) {
+ use_ogg = false;
+ }
+ 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();
+ }
+ {
+ ::FLAC__StreamDecoderInitStatus ret;
+ if ( !use_ogg ) {
+ ret = decoder.init();
+ } else {
+ ret = decoder.init_ogg();
+ }
+
+ if ( ret != FLAC__STREAM_DECODER_INIT_STATUS_OK ) {
+ goto end;
+ }
+ }
+
+ 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/empty.cc b/oss-fuzz/empty.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/oss-fuzz/empty.cc
diff --git a/oss-fuzz/encoder.cc b/oss-fuzz/encoder.cc
new file mode 100644
index 0000000..23cb397
--- /dev/null
+++ b/oss-fuzz/encoder.cc
@@ -0,0 +1,257 @@
+/* Copyright 2019 Guido Vranken
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+#include <fuzzing/datasource/datasource.hpp>
+#include <fuzzing/memory.hpp>
+
+#include "FLAC++/encoder.h"
+#include "common.h"
+
+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);
+
+ try {
+ const int channels = ds.Get<uint8_t>();
+ const int bps = ds.Get<uint8_t>();
+ encoder.set_channels(channels);
+ encoder.set_bits_per_sample(bps);
+
+ {
+ 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);
+ }
+ {
+ const bool res = encoder.set_blocksize(ds.Get<uint16_t>());
+ fuzzing::memory::memory_test(res);
+ }
+ {
+ const bool res = encoder.set_limit_min_bitrate(ds.Get<bool>());
+ fuzzing::memory::memory_test(res);
+ }
+ {
+ const bool res = encoder.set_sample_rate(ds.Get<uint32_t>());
+ fuzzing::memory::memory_test(res);
+ }
+
+ if ( size > 2 * 65535 * 4 ) {
+ /* With large inputs and expensive options enabled, the fuzzer can get *really* slow.
+ * Some combinations can make the fuzzer timeout (>60 seconds). However, while combining
+ * options makes the fuzzer slower, most options do not expose new code when combined.
+ * Therefore, combining slow options is disabled for large inputs. Any input containing
+ * more than 65536 * 2 samples of 32 bits each (max blocksize, stereo) is considered large
+ */
+ encoder.set_do_qlp_coeff_prec_search(false);
+ encoder.set_do_exhaustive_model_search(false);
+ }
+ if ( size > 2 * 4096 * 4 + 250 ) {
+ /* With subdivide_tukey in the mix testing apodizations can get really expensive. Therefore
+ * this is disabled for inputs of more than one whole stereo block of 32-bit inputs plus a
+ * bit of overhead */
+ encoder.set_apodization("");
+ }
+
+ {
+ ::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;
+ }
+ }
+
+ /* These sets must fail, because encoder is already initialized */
+ {
+ bool res = false;
+ res = res || encoder.set_streamable_subset(true);
+ res = res || encoder.set_ogg_serial_number(0);
+ res = res || encoder.set_verify(true);
+ res = res || encoder.set_compression_level(0);
+ res = res || encoder.set_do_exhaustive_model_search(true);
+ res = res || encoder.set_do_mid_side_stereo(true);
+ res = res || encoder.set_loose_mid_side_stereo(true);
+ res = res || encoder.set_apodization("test");
+ res = res || encoder.set_max_lpc_order(0);
+ res = res || encoder.set_qlp_coeff_precision(0);
+ res = res || encoder.set_do_qlp_coeff_prec_search(true);
+ res = res || encoder.set_do_escape_coding(true);
+ res = res || encoder.set_min_residual_partition_order(0);
+ res = res || encoder.set_max_residual_partition_order(0);
+ res = res || encoder.set_rice_parameter_search_dist(0);
+ res = res || encoder.set_total_samples_estimate(0);
+ res = res || encoder.set_channels(channels);
+ res = res || encoder.set_bits_per_sample(16);
+ res = res || encoder.set_limit_min_bitrate(true);
+ res = res || encoder.set_blocksize(3021);
+ res = res || encoder.set_sample_rate(44100);
+ fuzzing::memory::memory_test(res);
+ if(res)
+ abort();
+ }
+
+
+ {
+ /* XORing values as otherwise compiler will optimize, apparently */
+ bool res = false;
+ res = res != encoder.get_streamable_subset();
+ res = res != encoder.get_verify();
+ res = res != encoder.get_do_exhaustive_model_search();
+ res = res != encoder.get_do_mid_side_stereo();
+ res = res != encoder.get_loose_mid_side_stereo();
+ res = res != encoder.get_max_lpc_order();
+ res = res != encoder.get_qlp_coeff_precision();
+ res = res != encoder.get_do_qlp_coeff_prec_search();
+ res = res != encoder.get_do_escape_coding();
+ res = res != encoder.get_min_residual_partition_order();
+ res = res != encoder.get_max_residual_partition_order();
+ res = res != encoder.get_rice_parameter_search_dist();
+ res = res != encoder.get_total_samples_estimate();
+ res = res != encoder.get_channels();
+ res = res != encoder.get_bits_per_sample();
+ res = res != encoder.get_limit_min_bitrate();
+ res = res != encoder.get_blocksize();
+ res = res != encoder.get_sample_rate();
+ fuzzing::memory::memory_test(res);
+ }
+
+
+ while ( ds.Get<bool>() ) {
+ {
+ auto dat = ds.GetVector<FLAC__int32>();
+
+ if( ds.Get<bool>() )
+ /* Mask */
+ for (size_t i = 0; i < dat.size(); i++)
+ /* If we get here, bps is 4 or larger, or init will have failed */
+ dat[i] = (int32_t)(((uint32_t)(dat[i]) << (32-bps)) >> (32-bps));
+
+ const uint32_t samples = dat.size() / channels;
+ 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/encoder_v2.cc b/oss-fuzz/encoder_v2.cc
new file mode 100644
index 0000000..6448346
--- /dev/null
+++ b/oss-fuzz/encoder_v2.cc
@@ -0,0 +1,352 @@
+/* fuzzer_encoder_v2
+ * Copyright (C) 2022-2023 Xiph.Org Foundation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the Xiph.org Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 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 FOUNDATION 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 <cstdlib>
+#include <cstring> /* for memcpy */
+#include "FLAC/stream_encoder.h"
+#include "FLAC/metadata.h"
+extern "C" {
+#include "share/private.h"
+}
+#include "common.h"
+
+/* This C++ fuzzer uses the FLAC and not FLAC++ because the latter lacks a few
+ * hidden functions like FLAC__stream_encoder_disable_constant_subframes. It
+ * is still processed by a C++ compiler because that's what oss-fuzz expects */
+
+
+static FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, uint32_t samples, uint32_t current_frame, void *client_data)
+{
+ (void)encoder, (void)buffer, (void)bytes, (void)samples, (void)current_frame, (void)client_data;
+ return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ FLAC__bool encoder_valid = true;
+ FLAC__StreamEncoder *encoder = 0;
+ FLAC__StreamEncoderState state;
+ FLAC__StreamMetadata *metadata[16] = {NULL};
+ unsigned num_metadata = 0;
+ FLAC__StreamMetadata_VorbisComment_Entry VorbisCommentField;
+
+ unsigned sample_rate, channels, bps;
+ uint64_t samples_estimate, samples_in_input;
+ unsigned compression_level, input_data_width, blocksize, max_lpc_order, qlp_coeff_precision, min_residual_partition_order, max_residual_partition_order, metadata_mask, instruction_set_disable_mask;
+ FLAC__bool ogg, write_to_file, interleaved;
+
+ FLAC__bool data_bools[24];
+
+ /* Set alloc threshold. This check was added later and no spare config
+ * bytes were left, so we're reusing the sample rate as that of little
+ * consequence to the encoder and decoder except reading the frame header */
+
+ if(size < 3)
+ return 0;
+ alloc_check_threshold = data[2];
+ alloc_check_counter = 0;
+
+ /* allocate the encoder */
+ if((encoder = FLAC__stream_encoder_new()) == NULL) {
+ fprintf(stderr, "ERROR: allocating encoder\n");
+ return 1;
+ }
+
+ /* Use first 20 byte for configuration */
+ if(size < 20){
+ FLAC__stream_encoder_delete(encoder);
+ return 0;
+ }
+
+ /* First 3 byte for sample rate, 4th byte for channels, 5th byte for bps */
+ sample_rate = ((unsigned)data[0] << 16) + ((unsigned)data[1] << 8) + data[2];
+ channels = data[3];
+ bps = data[4];
+
+ /* Number of samples estimate, format accepts 36-bit max */
+ samples_estimate = ((uint64_t)data[5] << 32) + ((unsigned)data[6] << 24) + ((unsigned)data[7] << 16) + ((unsigned)data[8] << 8) + data[9];
+
+ compression_level = data[10]&0b1111;
+ input_data_width = 1 + (data[10]>>4)%4;
+ samples_in_input = (size-20)/input_data_width;
+ blocksize = ((unsigned)data[11] << 8) + (unsigned)data[12];
+ max_lpc_order = data[13];
+ qlp_coeff_precision = data[14];
+ min_residual_partition_order = data[15] & 0b1111;
+ max_residual_partition_order = data[15] & 0b11110000;
+ metadata_mask = data[16];
+ instruction_set_disable_mask = data[17];
+
+ /* Get array of bools from configuration */
+ for(int i = 0; i < 16; i++)
+ data_bools[i] = data[18+i/8] & (1 << (i % 8));
+
+ ogg = data_bools[0];
+ interleaved = data_bools[1];
+ write_to_file = data_bools[13];
+
+ /* Set input and process parameters */
+ encoder_valid &= FLAC__stream_encoder_set_verify(encoder, data_bools[2]);
+ encoder_valid &= FLAC__stream_encoder_set_channels(encoder, channels);
+ encoder_valid &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps);
+ encoder_valid &= FLAC__stream_encoder_set_sample_rate(encoder, sample_rate);
+ encoder_valid &= FLAC__stream_encoder_set_total_samples_estimate(encoder, samples_estimate);
+ encoder_valid &= FLAC__stream_encoder_disable_instruction_set(encoder, instruction_set_disable_mask);
+ encoder_valid &= FLAC__stream_encoder_set_limit_min_bitrate(encoder, data_bools[15]);
+
+ /* Set compression related parameters */
+ encoder_valid &= FLAC__stream_encoder_set_compression_level(encoder, compression_level);
+ if(data_bools[3]){
+ /* Bias towards regular compression levels */
+ encoder_valid &= FLAC__stream_encoder_set_blocksize(encoder, blocksize);
+ encoder_valid &= FLAC__stream_encoder_set_max_lpc_order(encoder, max_lpc_order);
+ encoder_valid &= FLAC__stream_encoder_set_qlp_coeff_precision(encoder, qlp_coeff_precision);
+ encoder_valid &= FLAC__stream_encoder_set_min_residual_partition_order(encoder, min_residual_partition_order);
+
+ /* With large inputs and expensive options enabled, the fuzzer can get *really* slow.
+ * Some combinations can make the fuzzer timeout (>60 seconds). However, while combining
+ * options makes the fuzzer slower, most options do not expose new code when combined.
+ * Therefore, combining slow options is disabled for large inputs. Any input containing
+ * more than 65536 * 2 samples (max blocksize, stereo) is considered large
+ */
+ if(samples_in_input < (2*65536)) {
+ encoder_valid &= FLAC__stream_encoder_set_streamable_subset(encoder, data_bools[4]);
+ encoder_valid &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, data_bools[5]);
+ encoder_valid &= FLAC__stream_encoder_set_do_escape_coding(encoder, data_bools[6]);
+ encoder_valid &= FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, data_bools[7]);
+ /* Combining model search, precision search and a high residual partition order is especially
+ * expensive, so limit that even further. This high partition order can only be set on
+ * large blocksize and with streamable subset disabled */
+ if(samples_in_input < (2 * 4609) || data_bools[4] || !data_bools[7] || !data_bools[5] || max_residual_partition_order < 9 || blocksize < 4609)
+ encoder_valid &= FLAC__stream_encoder_set_max_residual_partition_order(encoder, max_residual_partition_order);
+ }
+ else {
+ if(!data_bools[4])
+ encoder_valid &= FLAC__stream_encoder_set_streamable_subset(encoder, false);
+ else if(data_bools[6])
+ encoder_valid &= FLAC__stream_encoder_set_do_escape_coding(encoder, true);
+ else if(data_bools[7])
+ encoder_valid &= FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, true);
+ else if(data_bools[5])
+ encoder_valid &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, true);
+ }
+ encoder_valid &= FLAC__stream_encoder_set_do_mid_side_stereo(encoder, data_bools[8]);
+ encoder_valid &= FLAC__stream_encoder_set_loose_mid_side_stereo(encoder, data_bools[9]);
+
+ encoder_valid &= FLAC__stream_encoder_disable_constant_subframes(encoder, data_bools[10]);
+ encoder_valid &= FLAC__stream_encoder_disable_fixed_subframes(encoder, data_bools[11]);
+ encoder_valid &= FLAC__stream_encoder_disable_verbatim_subframes(encoder, data_bools[12]);
+ }
+
+ /* Disable alloc check if requested */
+ if(encoder_valid && data_bools[14])
+ alloc_check_threshold = INT32_MAX;
+
+ /* add metadata */
+ if(encoder_valid && (metadata_mask & 1)) {
+ if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO)) == NULL)
+ encoder_valid = false;
+ else
+ num_metadata++;
+ }
+ if(encoder_valid && (metadata_mask & 2) && size > 21){
+ if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL)
+ encoder_valid = false;
+ else {
+ metadata[num_metadata++]->length = (((unsigned)data[20]) << 8) + (unsigned)(data[21]);
+ }
+ }
+ if(encoder_valid && (metadata_mask & 4) && size > 20){
+ FLAC__byte * application_data = (FLAC__byte *)malloc(size-20);
+ if(0 != application_data && ((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)) == NULL))
+ encoder_valid = false;
+ else {
+ memcpy(application_data,data+20,size-20);
+ FLAC__metadata_object_application_set_data(metadata[num_metadata++], application_data, size-20, 0);
+ }
+ }
+ if(encoder_valid && (metadata_mask & 8) && size > 25){
+ if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE)) == NULL)
+ encoder_valid = false;
+ else {
+ unsigned seekpoint_spacing = ((unsigned)data[22] << 8) + data[23];
+ unsigned total_samples_for_seekpoints = ((unsigned)data[24] << 8) + data[25];
+ FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(metadata[num_metadata++], seekpoint_spacing, total_samples_for_seekpoints);
+ }
+ }
+ if(encoder_valid && (metadata_mask & 16)){
+ if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) != NULL) {
+ bool vorbiscomment_valid = true;
+ /* Append a vorbis comment */
+ if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&VorbisCommentField, "COMMENTARY", "Nothing to 🤔 report"))
+ vorbiscomment_valid = false;
+ else {
+ if(FLAC__metadata_object_vorbiscomment_append_comment(metadata[num_metadata], VorbisCommentField, false)) {
+
+ /* Insert a vorbis comment at the first index */
+ if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&VorbisCommentField, "COMMENTARY", "Still nothing to report 🤔🤣"))
+ vorbiscomment_valid = false;
+ else
+ if(!FLAC__metadata_object_vorbiscomment_insert_comment(metadata[num_metadata], 0, VorbisCommentField, false)) {
+ free(VorbisCommentField.entry);
+ vorbiscomment_valid = false;
+ }
+ }
+ else {
+ free(VorbisCommentField.entry);
+ vorbiscomment_valid = false;
+ }
+ }
+ if(!vorbiscomment_valid) {
+ FLAC__metadata_object_delete(metadata[num_metadata]);
+ metadata[num_metadata] = 0;
+ }
+ else
+ num_metadata++;
+ }
+ }
+ if(encoder_valid && (metadata_mask & 32)){
+ if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)) != NULL) {
+ if(!FLAC__metadata_object_cuesheet_insert_blank_track(metadata[num_metadata],0)) {
+ FLAC__metadata_object_delete(metadata[num_metadata]);
+ metadata[num_metadata] = 0;
+ }
+ else {
+ if(!FLAC__metadata_object_cuesheet_track_insert_blank_index(metadata[num_metadata],0,0)) {
+ FLAC__metadata_object_delete(metadata[num_metadata]);
+ metadata[num_metadata] = 0;
+ }
+ else {
+ metadata[num_metadata]->data.cue_sheet.tracks[0].number = 1;
+ num_metadata++;
+ }
+ }
+ }
+ }
+ if(encoder_valid && (metadata_mask & 64)){
+ if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE)) != NULL) {
+ num_metadata++;
+ }
+ }
+ if(encoder_valid && (metadata_mask & 128)){
+ if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_UNDEFINED)) != NULL) {
+ metadata[num_metadata]->length = 24;
+ metadata[num_metadata]->data.unknown.data = (FLAC__byte *)calloc(24, 1);
+ num_metadata++;
+ }
+ }
+
+ if(num_metadata && encoder_valid)
+ encoder_valid = FLAC__stream_encoder_set_metadata(encoder, metadata, num_metadata);
+
+ /* initialize encoder */
+ if(encoder_valid) {
+ FLAC__StreamEncoderInitStatus init_status;
+ if(ogg)
+ if(write_to_file)
+ init_status = FLAC__stream_encoder_init_ogg_file(encoder, "/tmp/tmp.flac", NULL, NULL);
+ else
+ init_status = FLAC__stream_encoder_init_ogg_stream(encoder, NULL, write_callback, NULL, NULL, NULL, NULL);
+ else
+ if(write_to_file)
+ init_status = FLAC__stream_encoder_init_file(encoder, "/tmp/tmp.flac", NULL, NULL);
+ else
+ init_status = FLAC__stream_encoder_init_stream(encoder, write_callback, NULL, NULL, NULL, NULL);
+ if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
+ encoder_valid = false;
+ }
+ }
+
+
+ /* send samples to encoder */
+ if(encoder_valid && size > (input_data_width*channels+26)) {
+ unsigned samples = (size - 26)/input_data_width/channels;
+ const uint8_t * pcm_data = data + 26;
+ int32_t * data_as_int32 = (int32_t *)malloc(4*samples*channels);
+ if(0 != data_as_int32){
+ for(unsigned i = 0; i < samples*channels; i++)
+ if(input_data_width == 1)
+ data_as_int32[i] = (int32_t)pcm_data[i] - 0x80;
+ else if(input_data_width == 2)
+ data_as_int32[i] = (((int32_t)pcm_data[i*2] << 8) + pcm_data[i*2+1]) - 0x8000;
+ else if(input_data_width == 3)
+ data_as_int32[i] = (((int32_t)pcm_data[i*3] << 16) + ((int32_t)pcm_data[i*3+1] << 8) + pcm_data[i*3+2]) - 0x800000;
+ else if(input_data_width == 4)
+ data_as_int32[i] = (((int64_t)pcm_data[i*4] << 24) + ((int32_t)pcm_data[i*4+1] << 16) + ((int32_t)pcm_data[i*4+2] << 8) + pcm_data[i*4+3]) - 0x80000000;
+
+ /* feed samples to encoder */
+ if(interleaved)
+ encoder_valid = FLAC__stream_encoder_process_interleaved(encoder, data_as_int32, samples);
+ else {
+ encoder_valid = FLAC__stream_encoder_process(encoder, (const int32_t*[]){data_as_int32,
+ data_as_int32+samples,
+ data_as_int32+samples*2,
+ data_as_int32+samples*3,
+ data_as_int32+samples*4, data_as_int32+samples*5, data_as_int32+samples*6, data_as_int32+samples*7}, samples);
+ }
+ free(data_as_int32);
+ }
+ else {
+ encoder_valid = false;
+ }
+ }
+
+ state = FLAC__stream_encoder_get_state(encoder);
+ if(!(state == FLAC__STREAM_ENCODER_OK ||
+ state == FLAC__STREAM_ENCODER_UNINITIALIZED ||
+ state == FLAC__STREAM_ENCODER_CLIENT_ERROR ||
+ ((state == FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR ||
+ state == FLAC__STREAM_ENCODER_FRAMING_ERROR ||
+ (state == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR &&
+ FLAC__stream_encoder_get_verify_decoder_state(encoder) == FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR)) &&
+ alloc_check_threshold < INT32_MAX))) {
+ fprintf(stderr,"-----\nERROR: stream encoder returned %s\n-----\n",FLAC__stream_encoder_get_resolved_state_string(encoder));
+ if(state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) {
+ uint32_t frame_number, channel, sample_number;
+ FLAC__int32 expected, got;
+ FLAC__stream_encoder_get_verify_decoder_error_stats(encoder, NULL, &frame_number, &channel, &sample_number, &expected, &got);
+ fprintf(stderr,"Frame number %d\nChannel %d\n Sample number %d\nExpected value %d\nGot %d\n", frame_number, channel, sample_number, expected, got);
+ }
+ abort();
+ }
+
+ FLAC__stream_encoder_finish(encoder);
+
+ /* now that encoding is finished, the metadata can be freed */
+ for(unsigned i = 0; i < 16; i++)
+ if(0 != metadata[i])
+ FLAC__metadata_object_delete(metadata[i]);
+
+ FLAC__stream_encoder_delete(encoder);
+
+ return 0;
+}
+
diff --git a/oss-fuzz/fuzzer_encoder.dict b/oss-fuzz/fuzzer_encoder.dict
new file mode 100644
index 0000000..9662137
--- /dev/null
+++ b/oss-fuzz/fuzzer_encoder.dict
@@ -0,0 +1,18 @@
+"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)"
+"subdivide_tukey(0)"
+"welch"
diff --git a/oss-fuzz/fuzzing/datasource/datasource.hpp b/oss-fuzz/fuzzing/datasource/datasource.hpp
new file mode 100644
index 0000000..3c9484e
--- /dev/null
+++ b/oss-fuzz/fuzzing/datasource/datasource.hpp
@@ -0,0 +1,190 @@
+/* Copyright 2019 Guido Vranken
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#pragma once
+
+#include <fuzzing/exception.hpp>
+#include <fuzzing/types.hpp>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <vector>
+
+namespace fuzzing {
+namespace datasource {
+
+class Base
+{
+ protected:
+ virtual std::vector<uint8_t> get(const size_t min, const size_t max, const uint64_t id = 0) = 0;
+ public:
+ Base(void) = default;
+ virtual ~Base(void) = default;
+
+ template<class T> T Get(const uint64_t id = 0);
+ uint16_t GetChoice(const uint64_t id = 0);
+ std::vector<uint8_t> GetData(const uint64_t id, const size_t min = 0, const size_t max = 0);
+ template <class T> std::vector<T> GetVector(const uint64_t id = 0);
+
+ class OutOfData : public fuzzing::exception::FlowException {
+ public:
+ OutOfData() = default;
+ };
+
+ class DeserializationFailure : public fuzzing::exception::FlowException {
+ public:
+ DeserializationFailure() = default;
+ };
+};
+
+#ifndef FUZZING_HEADERS_NO_IMPL
+template<class T> T Base::Get(const uint64_t id)
+{
+ T ret;
+ const auto v = get(sizeof(ret), sizeof(ret), id);
+ memcpy(&ret, v.data(), sizeof(ret));
+ return ret;
+}
+
+template <> bool Base::Get<bool>(const uint64_t id)
+{
+ uint8_t ret;
+ const auto v = get(sizeof(ret), sizeof(ret), id);
+ memcpy(&ret, v.data(), sizeof(ret));
+ return (ret % 2) ? true : false;
+}
+
+template <> std::string Base::Get<std::string>(const uint64_t id)
+{
+ auto data = GetData(id);
+ return std::string(data.data(), data.data() + data.size());
+}
+
+template <> std::vector<std::string> Base::Get<std::vector<std::string>>(const uint64_t id)
+{
+ std::vector<std::string> ret;
+ while ( true ) {
+ auto data = GetData(id);
+ ret.push_back( std::string(data.data(), data.data() + data.size()) );
+ if ( Get<bool>(id) == false ) {
+ break;
+ }
+ }
+ return ret;
+}
+
+uint16_t Base::GetChoice(const uint64_t id)
+{
+ return Get<uint16_t>(id);
+}
+
+std::vector<uint8_t> Base::GetData(const uint64_t id, const size_t min, const size_t max)
+{
+ return get(min, max, id);
+}
+
+
+template <> types::String<> Base::Get<types::String<>>(const uint64_t id) {
+ const auto data = GetData(id);
+ types::String<> ret(data.data(), data.size());
+ return ret;
+}
+
+template <> types::Data<> Base::Get<types::Data<>>(const uint64_t id) {
+ const auto data = GetData(id);
+ types::Data<> ret(data.data(), data.size());
+ return ret;
+}
+
+template <class T>
+std::vector<T> Base::GetVector(const uint64_t id) {
+ std::vector<T> ret;
+
+ while ( Get<bool>(id) == true ) {
+ ret.push_back( Get<T>(id) );
+ }
+
+ return ret;
+}
+#endif
+
+class Datasource : public Base
+{
+ private:
+ const uint8_t* data;
+ const size_t size;
+ size_t idx;
+ size_t left;
+ std::vector<uint8_t> get(const size_t min, const size_t max, const uint64_t id = 0) override;
+
+ // Make copy constructor and assignment operator private.
+ Datasource(const Datasource &) : data(0), size(0), idx(0), left(0) {}
+ Datasource& operator=(const Datasource &) { return *this; }
+ public:
+ Datasource(const uint8_t* _data, const size_t _size);
+};
+
+#ifndef FUZZING_HEADERS_NO_IMPL
+Datasource::Datasource(const uint8_t* _data, const size_t _size) :
+ Base(), data(_data), size(_size), idx(0), left(size)
+{
+}
+
+std::vector<uint8_t> Datasource::get(const size_t min, const size_t max, const uint64_t id) {
+ (void)id;
+
+ uint32_t getSize;
+ if ( left < sizeof(getSize) ) {
+ throw OutOfData();
+ }
+ memcpy(&getSize, data + idx, sizeof(getSize));
+ idx += sizeof(getSize);
+ left -= sizeof(getSize);
+
+ if ( getSize < min ) {
+ getSize = min;
+ }
+ if ( max && getSize > max ) {
+ getSize = max;
+ }
+
+ if ( left < getSize ) {
+ throw OutOfData();
+ }
+
+ std::vector<uint8_t> ret(getSize);
+
+ if ( getSize > 0 ) {
+ memcpy(ret.data(), data + idx, getSize);
+ }
+ idx += getSize;
+ left -= getSize;
+
+ return ret;
+}
+#endif
+
+} /* namespace datasource */
+} /* namespace fuzzing */
diff --git a/oss-fuzz/fuzzing/datasource/id.hpp b/oss-fuzz/fuzzing/datasource/id.hpp
new file mode 100644
index 0000000..457c984
--- /dev/null
+++ b/oss-fuzz/fuzzing/datasource/id.hpp
@@ -0,0 +1,75 @@
+/* Copyright 2019 Guido Vranken
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <stdint.h>
+#include <utility>
+#include <map>
+
+namespace fuzzing {
+namespace datasource {
+
+/* From: https://gist.github.com/underscorediscovery/81308642d0325fd386237cfa3b44785c */
+inline uint64_t hash_64_fnv1a(const void* key, const uint64_t len) {
+
+ const char* data = (char*)key;
+ uint64_t hash = 0xcbf29ce484222325;
+ uint64_t prime = 0x100000001b3;
+
+ for(uint64_t i = 0; i < len; ++i) {
+ uint8_t value = data[i];
+ hash = hash ^ value;
+ hash *= prime;
+ }
+
+ return hash;
+
+} //hash_64_fnv1a
+
+// FNV1a c++11 constexpr compile time hash functions, 32 and 64 bit
+// str should be a null terminated string literal, value should be left out
+// e.g hash_32_fnv1a_const("example")
+// code license: public domain or equivalent
+// post: https://notes.underscorediscovery.com/constexpr-fnv1a/
+
+constexpr uint32_t val_32_const = 0x811c9dc5;
+constexpr uint32_t prime_32_const = 0x1000193;
+constexpr uint64_t val_64_const = 0xcbf29ce484222325;
+constexpr uint64_t prime_64_const = 0x100000001b3;
+
+
+inline constexpr uint64_t ID(const char* const str, const uint64_t value = val_64_const) noexcept {
+ auto ret = (str[0] == '\0') ? value : ID(&str[1], (value ^ uint64_t(str[0])) * prime_64_const);
+ return ret;
+}
+
+inline constexpr std::pair<const char*, uint64_t> IDPair(const char* const str, const uint64_t value = val_64_const) noexcept {
+ return {str, ID(str, value)};
+}
+
+using IDMap = std::map<const char*, uint64_t>;
+
+} /* namespace datasource */
+} /* namespace fuzzing */
diff --git a/oss-fuzz/fuzzing/exception.hpp b/oss-fuzz/fuzzing/exception.hpp
new file mode 100644
index 0000000..d1ec580
--- /dev/null
+++ b/oss-fuzz/fuzzing/exception.hpp
@@ -0,0 +1,67 @@
+/* Copyright 2019 Guido Vranken
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#pragma once
+
+#include <exception>
+#include <string>
+
+namespace fuzzing {
+namespace exception {
+
+class ExceptionBase : public std::exception {
+ public:
+ ExceptionBase(void) = default;
+ /* typeid(T).name */
+};
+
+/* Recoverable exception */
+class FlowException : public ExceptionBase {
+ public:
+ FlowException(void) : ExceptionBase() { }
+};
+
+/* Error in this library, should never happen */
+class LogicException : public ExceptionBase {
+ private:
+ std::string reason;
+ public:
+ LogicException(const std::string r) : ExceptionBase(), reason(r) { }
+ virtual const char* what(void) const throw() {
+ return reason.c_str();
+ }
+};
+
+/* Error in target application */
+class TargetException : public ExceptionBase {
+ private:
+ std::string reason;
+ public:
+ TargetException(const std::string r) : ExceptionBase(), reason(r) { }
+ virtual const char* what(void) const throw() {
+ return reason.c_str();
+ }
+};
+
+} /* namespace exception */
+} /* namespace fuzzing */
diff --git a/oss-fuzz/fuzzing/memory.hpp b/oss-fuzz/fuzzing/memory.hpp
new file mode 100644
index 0000000..b324c36
--- /dev/null
+++ b/oss-fuzz/fuzzing/memory.hpp
@@ -0,0 +1,96 @@
+/* Copyright 2019 Guido Vranken
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <optional>
+
+#ifndef ASAN
+#define ASAN 0
+#endif
+
+#ifndef MSAN
+#define MSAN 0
+#endif
+
+namespace fuzzing {
+namespace memory {
+
+#ifndef FUZZING_HEADERS_NO_IMPL
+#if ASAN == 1
+extern "C" void *__asan_region_is_poisoned(const void *beg, size_t size);
+#endif
+
+#if MSAN == 1
+extern "C" void __msan_check_mem_is_initialized(const volatile void *x, size_t size);
+#endif
+
+void memory_test_asan(const void* data, const size_t size)
+{
+ (void)data;
+ (void)size;
+
+#if ASAN == 1
+ if ( __asan_region_is_poisoned(data, size) != NULL ) {
+ abort();
+ }
+#endif
+}
+
+void memory_test_msan(const void* data, const size_t size)
+{
+ (void)data;
+ (void)size;
+
+#if MSAN == 1
+ __msan_check_mem_is_initialized(data, size);
+#endif
+}
+
+void memory_test(const void* data, const size_t size)
+{
+ memory_test_asan(data, size);
+ memory_test_msan(data, size);
+}
+
+template <class T>
+void memory_test(const T& t)
+{
+ (void)t;
+}
+
+template <>
+void memory_test(const std::string& s)
+{
+ (void)s;
+
+#if MSAN == 1
+ memory_test(s.data(), s.size());
+#endif
+}
+
+#endif
+
+} /* namespace memory */
+} /* namespace fuzzing */
diff --git a/oss-fuzz/fuzzing/types.hpp b/oss-fuzz/fuzzing/types.hpp
new file mode 100644
index 0000000..914e64f
--- /dev/null
+++ b/oss-fuzz/fuzzing/types.hpp
@@ -0,0 +1,158 @@
+/* Copyright 2019 Guido Vranken
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <fuzzing/memory.hpp>
+#include <vector>
+#include <string>
+
+namespace fuzzing {
+namespace types {
+
+template <typename CoreType, bool NullTerminated, bool UseMSAN = false>
+class Container {
+ private:
+ CoreType* InvalidAddress = (CoreType*)0x12;
+
+ CoreType* _data = InvalidAddress;
+ size_t _size = 0;
+
+#ifndef FUZZING_HEADERS_NO_IMPL
+ void copy(const void* data, size_t size) {
+ if ( size > 0 ) {
+ std::memcpy(_data, data, size);
+ }
+ }
+
+ void allocate(size_t size) {
+ if ( size > 0 ) {
+ _data = static_cast<CoreType*>(malloc(size * sizeof(CoreType)));
+ } else {
+ _data = InvalidAddress;
+ }
+ };
+
+ void allocate_and_copy(const void* data, size_t size) {
+ allocate(size);
+ copy(data, size);
+ }
+
+ void allocate_plus_1_and_copy(const void* data, size_t size) {
+ allocate(size+1);
+ copy(data, size);
+ }
+
+ void access_hook(void) const {
+ if ( UseMSAN == true ) {
+ memory::memory_test_msan(_data, _size);
+ }
+ }
+
+ void free(void) {
+ access_hook();
+
+ if ( _data != InvalidAddress ) {
+ std::free(_data);
+ _data = InvalidAddress;
+ _size = 0;
+ }
+ }
+
+#endif
+
+ public:
+#ifndef FUZZING_HEADERS_NO_IMPL
+ CoreType* data(void) {
+ access_hook();
+ return _data;
+ }
+
+ size_t size(void) const {
+ access_hook();
+ return _size;
+ }
+#endif
+
+ Container(void)
+#ifndef FUZZING_HEADERS_NO_IMPL
+ = default
+#endif
+ ;
+
+ Container(const void* data, const size_t size)
+#ifndef FUZZING_HEADERS_NO_IMPL
+ {
+ if ( NullTerminated == false ) {
+ allocate_and_copy(data, size);
+ } else {
+ allocate_plus_1_and_copy(data, size);
+ _data[size] = 0;
+ }
+
+ access_hook();
+ }
+#endif
+ ;
+
+ template<class T>
+ Container(const T& t)
+#ifndef FUZZING_HEADERS_NO_IMPL
+ {
+ Container(t.data(), t.size());
+ }
+#endif
+ ;
+
+ ~Container(void)
+#ifndef FUZZING_HEADERS_NO_IMPL
+ {
+ this->free();
+ }
+#endif
+ ;
+
+
+
+ // The copy constructor was not originally explicitly supplied
+ // so it must have been incorrectly just copying the pointers.
+ Container(const Container &c) {
+ InvalidAddress = c.InvalidAddress;
+ allocate_and_copy(c._data, c._size);
+ }
+
+ Container& operator=(Container &c) {
+ InvalidAddress = c.InvalidAddress;
+ allocate_and_copy(c._data, c._size);
+ }
+
+};
+
+template <bool UseMSAN = false> using String = Container<char, true, UseMSAN>;
+template <bool UseMSAN = false> using Data = Container<uint8_t, false, UseMSAN>;
+
+} /* namespace types */
+} /* namespace fuzzing */
diff --git a/oss-fuzz/metadata.cc b/oss-fuzz/metadata.cc
new file mode 100644
index 0000000..ad27fe9
--- /dev/null
+++ b/oss-fuzz/metadata.cc
@@ -0,0 +1,526 @@
+/* fuzzer_metadata
+ * Copyright (C) 2022-2023 Xiph.Org Foundation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the Xiph.org Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 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 FOUNDATION 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 <cstdlib>
+#include <cstdio>
+#include <cstring> /* for memcpy */
+#include <unistd.h>
+#include "FLAC++/metadata.h"
+#include "common.h"
+
+#define CONFIG_LENGTH 2
+
+#define min(x,y) (x<y?x:y)
+
+static void run_tests_with_level_0_interface(char filename[]);
+static void run_tests_with_level_1_interface(char filename[], bool readonly, bool preservestats, const uint8_t *data, size_t size);
+static void run_tests_with_level_2_interface(char filename[], bool ogg, bool use_padding, const uint8_t *data, size_t size);
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ uint8_t command_length;
+ char filename[] = "/tmp/tmpXXXXXX.flac";
+ FLAC__bool init_bools[4];
+
+ /* Use first byte for configuration, leave at least one byte of input */
+ if(size < 1 + CONFIG_LENGTH){
+ return 0;
+ }
+
+ /* First 4 bits for configuration bools, next 4 for length of command section */
+ for(int i = 0; i < 4; i++)
+ init_bools[i] = data[i/8] & (1 << (i % 8));
+
+ command_length = data[0] >> 4;
+
+ if(0)//data[1] < 128) /* Use MSB as on/off */
+ alloc_check_threshold = data[1];
+ else
+ alloc_check_threshold = INT32_MAX;
+ alloc_check_counter = 0;
+
+
+ /* Leave at least one byte as input */
+ if(command_length >= size - 1 - CONFIG_LENGTH)
+ command_length = size - 1 - CONFIG_LENGTH;
+
+ /* Dump input to file */
+ {
+ int file_to_fuzz = mkstemps(filename, 5);
+
+ if (file_to_fuzz < 0)
+ abort();
+ write(file_to_fuzz,data+CONFIG_LENGTH+command_length,size-CONFIG_LENGTH-command_length);
+ close(file_to_fuzz);
+ }
+
+ run_tests_with_level_0_interface(filename);
+ run_tests_with_level_1_interface(filename, init_bools[1], init_bools[2], data+CONFIG_LENGTH, command_length/2);
+
+ /* Dump input to file, to start fresh for level 2 */
+ if(!init_bools[1]){
+ FILE * file_to_fuzz = fopen(filename,"w");
+ fwrite(data+CONFIG_LENGTH+command_length,1,size-CONFIG_LENGTH-command_length,file_to_fuzz);
+ fclose(file_to_fuzz);
+ }
+
+ run_tests_with_level_2_interface(filename, init_bools[0], init_bools[3], data+command_length/2+CONFIG_LENGTH, command_length/2);
+
+ remove(filename);
+
+ return 0;
+}
+
+static void run_tests_with_level_0_interface(char filename[]) {
+ FLAC::Metadata::StreamInfo streaminfo;
+ FLAC::Metadata::VorbisComment vorbis_comment;
+ FLAC::Metadata::CueSheet cue_sheet;
+ FLAC::Metadata::Picture picture;
+
+ FLAC::Metadata::get_streaminfo(filename,streaminfo);
+ FLAC::Metadata::get_tags(filename,vorbis_comment);
+ FLAC::Metadata::get_cuesheet(filename,cue_sheet);
+ FLAC::Metadata::get_picture(filename,picture, (FLAC__StreamMetadata_Picture_Type)(1), NULL, NULL, -1, -1, -1, -1);
+}
+
+static void run_tests_with_level_1_interface(char filename[], bool readonly, bool preservestats, const uint8_t *data, size_t size) {
+ FLAC::Metadata::SimpleIterator iterator;
+ FLAC::Metadata::Prototype *metadata_block = nullptr;
+ uint8_t id[4] = {0};
+
+ if(!iterator.is_valid())
+ return;
+
+ if(!iterator.init(filename,readonly,preservestats))
+ return;
+
+ for(size_t i = 0; i < size && iterator.status() == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; i++) {
+ switch(data[i] & 7) {
+ case 0:
+ iterator.get_block_type();
+ iterator.get_block_offset();
+ iterator.get_block_length();
+ iterator.get_application_id(id);
+ break;
+ case 1:
+ iterator.next();
+ break;
+ case 2:
+ iterator.prev();
+ break;
+ case 3:
+ iterator.delete_block(data[i] & 8);
+ break;
+ case 4:
+ if(metadata_block != 0) {
+ delete metadata_block;
+ metadata_block = nullptr;
+ }
+ metadata_block = iterator.get_block();
+ break;
+ case 5:
+ if(metadata_block != 0)
+ iterator.set_block(metadata_block,data[i] & 8);
+ break;
+ case 6:
+ if(metadata_block != 0)
+ iterator.insert_block_after(metadata_block, data[i] & 8);
+ break;
+ case 7:
+ iterator.status();
+ iterator.is_last();
+ iterator.is_writable();
+ break;
+ }
+ }
+ if(metadata_block != 0) {
+ delete metadata_block;
+ metadata_block = nullptr;
+ }
+
+
+}
+
+
+static void run_tests_with_level_2_interface(char filename[], bool ogg, bool use_padding, const uint8_t *data, size_t size) {
+ FLAC::Metadata::Chain chain;
+ FLAC::Metadata::Iterator iterator;
+ FLAC::Metadata::Prototype *metadata_block_get = nullptr;
+ FLAC::Metadata::Prototype *metadata_block_transfer = nullptr;
+ FLAC::Metadata::Prototype *metadata_block_put = nullptr;
+
+ if(!chain.is_valid())
+ return;
+
+ if(!chain.read(filename, ogg))
+ return;
+
+ iterator.init(chain);
+
+ for(size_t i = 0; i < size; i++) {
+ switch(data[i] & 15) {
+ case 0:
+ iterator.get_block_type();
+ break;
+ case 1:
+ iterator.next();
+ break;
+ case 2:
+ iterator.prev();
+ break;
+ case 3:
+ iterator.delete_block(data[i] & 16);
+ break;
+ case 4:
+ metadata_block_get = iterator.get_block();
+ if(metadata_block_get != 0 && metadata_block_get->is_valid()) {
+ if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
+ if(metadata_block_transfer != metadata_block_get) {
+ delete metadata_block_transfer;
+ metadata_block_transfer = nullptr;
+ metadata_block_transfer = FLAC::Metadata::clone(metadata_block_get);
+ }
+ }
+ else {
+ metadata_block_transfer = FLAC::Metadata::clone(metadata_block_get);
+ }
+ }
+ delete metadata_block_get;
+ break;
+ case 5:
+ if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
+ metadata_block_put = FLAC::Metadata::clone(metadata_block_transfer);
+ if(metadata_block_put != 0 && metadata_block_put->is_valid()) {
+ if(!iterator.insert_block_before(metadata_block_put))
+ delete metadata_block_put;
+ }
+ else
+ if(metadata_block_put != 0)
+ delete metadata_block_put;
+ }
+ break;
+ case 6:
+ if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
+ metadata_block_put = FLAC::Metadata::clone(metadata_block_transfer);
+ if(metadata_block_put != 0 && metadata_block_put->is_valid()) {
+ if(!iterator.insert_block_after(metadata_block_put))
+ delete metadata_block_put;
+ }
+ else
+ if(metadata_block_put != 0)
+ delete metadata_block_put;
+ }
+ break;
+ case 7:
+ if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
+ metadata_block_put = FLAC::Metadata::clone(metadata_block_transfer);
+ if(metadata_block_put != 0 && metadata_block_put->is_valid()) {
+ if(!iterator.set_block(metadata_block_put))
+ delete metadata_block_put;
+ }
+ else
+ if(metadata_block_put != 0)
+ delete metadata_block_put;
+ }
+ break;
+ case 8: /* Examine block */
+ if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
+ switch(metadata_block_transfer->get_type()) {
+ case FLAC__METADATA_TYPE_VORBIS_COMMENT:
+ {
+ uint32_t num_comments;
+ ::FLAC__StreamMetadata_VorbisComment_Entry entry;
+ FLAC::Metadata::VorbisComment::Entry entry_cpp;
+ FLAC::Metadata::VorbisComment * vorbiscomment = dynamic_cast<FLAC::Metadata::VorbisComment *>(metadata_block_transfer);
+ const ::FLAC__StreamMetadata * metadata_c = *metadata_block_transfer;
+ if(vorbiscomment == 0)
+ abort();
+ vorbiscomment->get_vendor_string();
+ num_comments = vorbiscomment->get_num_comments();
+ if(num_comments > 0) {
+ entry = metadata_c->data.vorbis_comment.comments[min(data[i]>>4,num_comments-1)];
+ if(entry.entry == 0)
+ abort();
+ if(vorbiscomment->get_comment(min(data[i]>>4,num_comments-1)).is_valid()) {
+ entry_cpp = vorbiscomment->get_comment(min(data[i]>>4,num_comments-1));
+ if(entry_cpp.is_valid() && entry_cpp.get_field() == 0)
+ abort();
+ vorbiscomment->find_entry_from(0,"TEST");
+ }
+ }
+
+ }
+ break;
+ case FLAC__METADATA_TYPE_CUESHEET:
+ {
+ uint32_t num_tracks, num_indices;
+ FLAC::Metadata::CueSheet * cuesheet = dynamic_cast<FLAC::Metadata::CueSheet *>(metadata_block_transfer);
+ if(cuesheet == 0 || !cuesheet->is_legal())
+ break;
+ cuesheet->is_legal(true); /* check CDDA subset */
+ cuesheet->calculate_cddb_id();
+ cuesheet->get_media_catalog_number();
+ cuesheet->get_lead_in();
+ cuesheet->get_is_cd();
+ num_tracks = cuesheet->get_num_tracks();
+ if(num_tracks > 0) {
+ FLAC::Metadata::CueSheet::Track track = cuesheet->get_track(min(data[i]>>4,num_tracks-1));
+ track.get_offset();
+ track.get_number();
+ track.get_isrc();
+ track.get_pre_emphasis();
+ num_indices = track.get_num_indices();
+ if(num_indices > 0) {
+ FLAC__StreamMetadata_CueSheet_Index index = track.get_index(min(data[i]>>4,num_indices-1));
+ (void)index;
+ }
+ }
+ }
+ break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ {
+ char * violation = nullptr;
+ FLAC::Metadata::Picture * picture = dynamic_cast<FLAC::Metadata::Picture *>(metadata_block_transfer);
+ if(picture == 0 || !picture->is_legal((const char **)&violation))
+ break;
+ picture->get_data();
+ }
+ break;
+ default:
+ break;
+ }
+
+ }
+ break;
+ case 9: /* Replace or add in block */
+ if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
+ switch(metadata_block_transfer->get_type()) {
+ case FLAC__METADATA_TYPE_SEEKTABLE:
+ {
+ uint32_t num_seekpoints;
+ FLAC__StreamMetadata_SeekPoint seekpoint;
+ FLAC::Metadata::SeekTable * seektable = dynamic_cast<FLAC::Metadata::SeekTable *>(metadata_block_transfer);
+ if(seektable == 0)
+ break;
+ if(seektable->is_valid() && seektable->is_legal()) {
+ num_seekpoints = seektable->get_num_points();
+ if(num_seekpoints > 0) {
+ seekpoint = seektable->get_point(min(data[i]>>5,num_seekpoints-1));
+ seektable->set_point(0,seekpoint);
+ seektable->insert_point(min(data[i]>>5,num_seekpoints-1),seekpoint);
+ }
+ seektable->template_append_placeholders(4);
+ seektable->template_append_point(111111);
+ seektable->template_append_points((FLAC__uint64[]){222222, 333333, 444444}, 3);
+ seektable->template_append_spaced_points(data[i]>>5, 1234567);
+ seektable->template_append_spaced_points_by_samples(data[i]>>5, 2468000);
+ seektable->template_sort(data[i] & 16);
+ }
+ }
+ case FLAC__METADATA_TYPE_VORBIS_COMMENT:
+ {
+ uint32_t num_comments;
+ FLAC::Metadata::VorbisComment::Entry entry;
+ FLAC::Metadata::VorbisComment * vorbiscomment = dynamic_cast<FLAC::Metadata::VorbisComment *>(metadata_block_transfer);
+ if(vorbiscomment == 0)
+ break;
+ num_comments = vorbiscomment->get_num_comments();
+ if(num_comments > 0 && entry.is_valid()) {
+ if(vorbiscomment->get_comment(min(data[i]>>5,num_comments-1)).is_valid()) {
+ entry = vorbiscomment->get_comment(min(data[i]>>5,num_comments-1));
+ if(entry.is_valid()) {
+ vorbiscomment->replace_comment(entry,data[i] & 16);
+ vorbiscomment->set_comment(0,entry);
+ vorbiscomment->append_comment(entry);
+ vorbiscomment->insert_comment(0,entry);
+ }
+ }
+ }
+ }
+ break;
+ case FLAC__METADATA_TYPE_CUESHEET:
+ {
+ uint32_t num_tracks, num_indices;
+ FLAC::Metadata::CueSheet * cuesheet = dynamic_cast<FLAC::Metadata::CueSheet *>(metadata_block_transfer);
+ if(cuesheet == 0 || !cuesheet->is_legal())
+ break;
+ num_tracks = cuesheet->get_num_tracks();
+ if(num_tracks > 0) {
+ FLAC::Metadata::CueSheet::Track track = cuesheet->get_track(min(data[i]>>4,num_tracks-1));
+ num_indices = track.get_num_indices();
+ if(num_indices > 0) {
+ FLAC__StreamMetadata_CueSheet_Index index = track.get_index(min(data[i]>>4,num_indices-1));
+ track.set_index(0,index);
+ cuesheet->insert_index(0,0,index);
+ cuesheet->insert_blank_index(0,0);
+ }
+ cuesheet->insert_blank_track(0);
+ cuesheet->insert_track(0,track);
+ cuesheet->resize_indices(min(data[i]>>4,num_tracks-1),data[i]>>4);
+ }
+ }
+ break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ {
+ FLAC::Metadata::Picture * picture = dynamic_cast<FLAC::Metadata::Picture *>(metadata_block_transfer);
+ const char testtext[] = "TEST";
+ if(picture == 0 || !picture->is_legal(NULL))
+ break;
+ picture->set_description((FLAC__byte *)&testtext);
+ picture->set_mime_type((const char *)&testtext);
+ picture->set_data((FLAC__byte *)&testtext,4);
+ }
+ break;
+ default:
+ break;
+ }
+
+ }
+ break;
+ case 10: /* Delete from block */
+ if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
+ switch(metadata_block_transfer->get_type()) {
+ case FLAC__METADATA_TYPE_SEEKTABLE:
+ {
+ uint32_t num_seekpoints;
+ FLAC::Metadata::SeekTable * seektable = dynamic_cast<FLAC::Metadata::SeekTable *>(metadata_block_transfer);
+ if(seektable == 0)
+ break;
+ if(seektable->is_valid() && seektable->is_legal()) {
+ num_seekpoints = seektable->get_num_points();
+ if(num_seekpoints > 0)
+ seektable->delete_point(min(data[i]>>4,num_seekpoints-1));
+ }
+ }
+ case FLAC__METADATA_TYPE_VORBIS_COMMENT:
+ {
+ uint32_t num_comments;
+ FLAC::Metadata::VorbisComment * vorbiscomment = dynamic_cast<FLAC::Metadata::VorbisComment *>(metadata_block_transfer);
+ if(vorbiscomment == 0)
+ break;
+ num_comments = vorbiscomment->get_num_comments();
+ if(num_comments > 0)
+ vorbiscomment->delete_comment(min(data[i]>>4,num_comments-1));
+ vorbiscomment->remove_entry_matching("TEST");
+ vorbiscomment->remove_entries_matching("TEST");
+ }
+ break;
+ case FLAC__METADATA_TYPE_CUESHEET:
+ {
+ uint32_t num_tracks;
+ FLAC::Metadata::CueSheet * cuesheet = dynamic_cast<FLAC::Metadata::CueSheet *>(metadata_block_transfer);
+ if(cuesheet == 0 || !cuesheet->is_legal())
+ break;
+ num_tracks = cuesheet->get_num_tracks();
+ if(num_tracks > 0) {
+ FLAC::Metadata::CueSheet::Track track = cuesheet->get_track(min(data[i]>>4,num_tracks-1));
+ if(track.get_num_indices() > 0)
+ cuesheet->delete_index(min(data[i]>>4,num_tracks-1),0);
+ cuesheet->delete_track(0);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ }
+ break;
+ case 11: /* Resize block */
+ if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
+ switch(metadata_block_transfer->get_type()) {
+ case FLAC__METADATA_TYPE_PADDING:
+ {
+ FLAC::Metadata::Padding * padding = dynamic_cast<FLAC::Metadata::Padding *>(metadata_block_transfer);
+ if(padding == 0)
+ break;
+ padding->set_length(data[i]>>4);
+ }
+ break;
+ case FLAC__METADATA_TYPE_SEEKTABLE:
+ {
+ FLAC::Metadata::SeekTable * seektable = dynamic_cast<FLAC::Metadata::SeekTable *>(metadata_block_transfer);
+ if(seektable == 0)
+ break;
+ seektable->resize_points(data[i]>>4);
+ }
+ break;
+ case FLAC__METADATA_TYPE_VORBIS_COMMENT:
+ {
+ FLAC::Metadata::VorbisComment * vorbiscomment = dynamic_cast<FLAC::Metadata::VorbisComment *>(metadata_block_transfer);
+ if(vorbiscomment == 0)
+ break;
+ vorbiscomment->resize_comments(data[i]>>4);
+ }
+ break;
+ case FLAC__METADATA_TYPE_CUESHEET:
+ {
+ uint32_t num_tracks;
+ FLAC::Metadata::CueSheet * cuesheet = dynamic_cast<FLAC::Metadata::CueSheet *>(metadata_block_transfer);
+ if(cuesheet == 0 || !cuesheet->is_legal())
+ break;
+ num_tracks = cuesheet->get_num_tracks();
+ if(num_tracks > 0) {
+ cuesheet->resize_indices(min(data[i]>>4,num_tracks-1),data[i]>>4);
+ }
+ cuesheet->resize_tracks(data[i]<<4);
+ }
+ break;
+ default:
+ break;
+ }
+
+ }
+ break;
+ case 12: /* Prototype functions */
+ if(metadata_block_transfer != 0 && metadata_block_transfer->is_valid()) {
+ const ::FLAC__StreamMetadata * metadata_compare = *metadata_block_transfer;
+ metadata_block_transfer->get_is_last();
+ metadata_block_transfer->get_length();
+ metadata_block_transfer->set_is_last(data[i] & 16);
+ FLAC__metadata_object_is_equal(metadata_compare, metadata_compare);
+ }
+ break;
+ }
+ }
+ if(metadata_block_transfer != 0) {
+ delete metadata_block_transfer;
+ metadata_block_transfer = nullptr;
+ }
+
+ chain.status();
+ chain.sort_padding();
+ chain.merge_padding();
+
+ chain.check_if_tempfile_needed(!use_padding);
+ chain.write(use_padding);
+
+}
diff --git a/oss-fuzz/reencoder.cc b/oss-fuzz/reencoder.cc
new file mode 100644
index 0000000..457fbd4
--- /dev/null
+++ b/oss-fuzz/reencoder.cc
@@ -0,0 +1,304 @@
+/* Copyright 2019 Guido Vranken
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+#include <fuzzing/datasource/datasource.hpp>
+#include <fuzzing/memory.hpp>
+
+#include "FLAC++/encoder.h"
+#include "FLAC++/decoder.h"
+#include "FLAC++/metadata.h"
+#include "common.h"
+
+#define MAX_NUM_METADATA_BLOCKS 2048
+
+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);
+ return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+ }
+ };
+ }
+ namespace Decoder {
+ class FuzzerDecoder : public Stream {
+ private:
+ fuzzing::datasource::Datasource& ds;
+ FLAC::Encoder::FuzzerStream& encoder;
+ public:
+ FuzzerDecoder(fuzzing::datasource::Datasource& dsrc, FLAC::Encoder::FuzzerStream& encoder_arg) :
+ Stream(), ds(dsrc), encoder(encoder_arg) { }
+
+ ::FLAC__StreamMetadata * metadata_blocks[MAX_NUM_METADATA_BLOCKS] = {0};
+ int num_metadata_blocks = 0;
+
+ void metadata_callback(const ::FLAC__StreamMetadata *metadata) override {
+ if(num_metadata_blocks < MAX_NUM_METADATA_BLOCKS)
+ if((metadata_blocks[num_metadata_blocks] = FLAC__metadata_object_clone(metadata)) != NULL)
+ num_metadata_blocks++;
+ }
+
+ ::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);
+ }
+ }
+
+ /* Data is checked, now pass it towards encoder */
+ if(encoder.get_state() == FLAC__STREAM_ENCODER_OK) {
+ if(encoder.get_channels() != get_channels())
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ if(encoder.get_bits_per_sample() != get_bits_per_sample())
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ encoder.process(buffer, frame->header.blocksize);
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+ }
+ else
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ }
+ void error_callback(::FLAC__StreamDecoderErrorStatus status) override {
+ fuzzing::memory::memory_test(status);
+ }
+ };
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ fuzzing::datasource::Datasource ds(data, size);
+ FLAC::Encoder::FuzzerStream encoder(ds);
+ FLAC::Decoder::FuzzerDecoder decoder(ds, encoder);
+
+ try {
+ const int channels = ds.Get<uint8_t>();
+ const int bps = ds.Get<uint8_t>();
+ encoder.set_channels(channels);
+ encoder.set_bits_per_sample(bps);
+
+ {
+ 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_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 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_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_total_samples_estimate(ds.Get<uint64_t>());
+ fuzzing::memory::memory_test(res);
+ }
+ {
+ const bool res = encoder.set_blocksize(ds.Get<uint16_t>());
+ fuzzing::memory::memory_test(res);
+ }
+ {
+ const bool res = encoder.set_limit_min_bitrate(ds.Get<bool>());
+ fuzzing::memory::memory_test(res);
+ }
+ {
+ const bool res = encoder.set_sample_rate(ds.Get<uint32_t>());
+ fuzzing::memory::memory_test(res);
+ }
+
+ decoder.set_metadata_respond_all();
+
+ {
+ ::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;
+ }
+
+ decoder.process_until_end_of_metadata();
+ if(decoder.num_metadata_blocks > 0)
+ encoder.set_metadata(decoder.metadata_blocks, decoder.num_metadata_blocks);
+ }
+
+ {
+ ::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;
+ }
+ }
+
+ /* These sets must fail, because encoder is already initialized */
+ {
+ bool res = false;
+ res = res || encoder.set_streamable_subset(true);
+ res = res || encoder.set_ogg_serial_number(0);
+ res = res || encoder.set_verify(true);
+ res = res || encoder.set_compression_level(0);
+ res = res || encoder.set_do_exhaustive_model_search(true);
+ res = res || encoder.set_do_mid_side_stereo(true);
+ res = res || encoder.set_loose_mid_side_stereo(true);
+ res = res || encoder.set_apodization("test");
+ res = res || encoder.set_max_lpc_order(0);
+ res = res || encoder.set_qlp_coeff_precision(0);
+ res = res || encoder.set_do_qlp_coeff_prec_search(true);
+ res = res || encoder.set_do_escape_coding(true);
+ res = res || encoder.set_min_residual_partition_order(0);
+ res = res || encoder.set_max_residual_partition_order(0);
+ res = res || encoder.set_rice_parameter_search_dist(0);
+ res = res || encoder.set_total_samples_estimate(0);
+ res = res || encoder.set_channels(channels);
+ res = res || encoder.set_bits_per_sample(16);
+ res = res || encoder.set_limit_min_bitrate(true);
+ res = res || encoder.set_blocksize(3021);
+ res = res || encoder.set_sample_rate(44100);
+ fuzzing::memory::memory_test(res);
+ if(res)
+ abort();
+ }
+
+
+ {
+ /* XORing values as otherwise compiler will optimize, apparently */
+ bool res = false;
+ res = res != encoder.get_streamable_subset();
+ res = res != encoder.get_verify();
+ res = res != encoder.get_do_exhaustive_model_search();
+ res = res != encoder.get_do_mid_side_stereo();
+ res = res != encoder.get_loose_mid_side_stereo();
+ res = res != encoder.get_max_lpc_order();
+ res = res != encoder.get_qlp_coeff_precision();
+ res = res != encoder.get_do_qlp_coeff_prec_search();
+ res = res != encoder.get_do_escape_coding();
+ res = res != encoder.get_min_residual_partition_order();
+ res = res != encoder.get_max_residual_partition_order();
+ res = res != encoder.get_rice_parameter_search_dist();
+ res = res != encoder.get_total_samples_estimate();
+ res = res != encoder.get_channels();
+ res = res != encoder.get_bits_per_sample();
+ res = res != encoder.get_limit_min_bitrate();
+ res = res != encoder.get_blocksize();
+ res = res != encoder.get_sample_rate();
+ fuzzing::memory::memory_test(res);
+ }
+
+ decoder.process_until_end_of_stream();
+
+ } catch ( ... ) { }
+
+end:
+ {
+ const bool res = encoder.finish();
+ fuzzing::memory::memory_test(res);
+ }
+ {
+ const bool res = decoder.finish();
+ fuzzing::memory::memory_test(res);
+ }
+ for(int i = 0; i < decoder.num_metadata_blocks; i++)
+ FLAC__metadata_object_delete(decoder.metadata_blocks[i]);
+
+ return 0;
+}
diff --git a/oss-fuzz/seek.cc b/oss-fuzz/seek.cc
new file mode 100644
index 0000000..d3ccbe8
--- /dev/null
+++ b/oss-fuzz/seek.cc
@@ -0,0 +1,195 @@
+/* fuzzer_seek
+ * Copyright (C) 2022-2023 Xiph.Org Foundation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the Xiph.org Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 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 FOUNDATION 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 <cstdlib>
+#include <cstring> /* for memcpy */
+#include "FLAC/stream_decoder.h"
+#include "common.h"
+
+int write_abort_check_counter = -1;
+
+#if 0 /* set to 1 to debug */
+#define FPRINTF_DEBUG_ONLY(...) fprintf(__VA_ARGS__)
+#else
+#define FPRINTF_DEBUG_ONLY(...)
+#endif
+
+#define CONFIG_LENGTH 2
+
+static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
+{
+ (void)decoder, (void)frame, (void)buffer, (void)client_data;
+ if(write_abort_check_counter > 0) {
+ write_abort_check_counter--;
+ if(write_abort_check_counter == 0)
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ } else if(write_abort_check_counter == 0)
+ /* This must not happen: write callback called after abort is returned */
+ abort();
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus error, void *client_data)
+{
+ (void)decoder, (void)error, (void)client_data;
+}
+
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ FLAC__bool decoder_valid = true;
+ FLAC__StreamDecoder *decoder;
+ uint8_t command_length;
+ FLAC__bool init_bools[16], ogg;
+
+ if(size > 2 && data[1] < 128) /* Use MSB as on/off */
+ alloc_check_threshold = data[1];
+ else
+ alloc_check_threshold = INT32_MAX;
+ alloc_check_counter = 0;
+
+ write_abort_check_counter = -1;
+
+ /* allocate the decoder */
+ if((decoder = FLAC__stream_decoder_new()) == NULL) {
+ fprintf(stderr, "ERROR: allocating decoder\n");
+ return 1;
+ }
+
+ /* Use first byte for configuration, leave at least one byte of input */
+ if(size < 1 + CONFIG_LENGTH){
+ FLAC__stream_decoder_delete(decoder);
+ return 0;
+ }
+
+ /* First 4 bits for configuration bools, next 4 for length of command section */
+ for(int i = 0; i < 4; i++)
+ init_bools[i] = data[i/8] & (1 << (i % 8));
+
+ command_length = data[0] >> 4;
+
+ /* Leave at least one byte as input */
+ if(command_length >= size - 1 - CONFIG_LENGTH)
+ command_length = size - 1 - CONFIG_LENGTH;
+
+ /* Dump decoder input to file */
+ {
+ FILE * file_to_decode = fopen("/tmp/tmp.flac","w");
+ fwrite(data+CONFIG_LENGTH+command_length,1,size-CONFIG_LENGTH-command_length,file_to_decode);
+ fclose(file_to_decode);
+ }
+
+ ogg = init_bools[0];
+
+ FLAC__stream_decoder_set_md5_checking(decoder,init_bools[1]);
+ if(init_bools[2])
+ FLAC__stream_decoder_set_metadata_respond_all(decoder);
+ if(init_bools[3])
+ FLAC__stream_decoder_set_metadata_ignore_all(decoder);
+
+ /* initialize decoder */
+ if(decoder_valid) {
+ FLAC__StreamDecoderInitStatus init_status;
+ if(ogg)
+ init_status = FLAC__stream_decoder_init_ogg_file(decoder, "/tmp/tmp.flac", write_callback, NULL, error_callback, NULL);
+ else
+ init_status = FLAC__stream_decoder_init_file(decoder, "/tmp/tmp.flac", write_callback, NULL, error_callback, NULL);
+ if(init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+ decoder_valid = false;
+ }
+ }
+
+ /* Run commands */
+ for(uint8_t i = 0; decoder_valid && (i < command_length); i++){
+ const uint8_t * command = data+CONFIG_LENGTH+i;
+ uint8_t shift = 1u << (command[0] >> 3);
+ FLAC__uint64 seekpos;
+
+ switch(command[0] & 15){
+ case 0:
+ FPRINTF_DEBUG_ONLY(stderr,"end_of_stream\n");
+ decoder_valid = FLAC__stream_decoder_process_until_end_of_stream(decoder);
+ break;
+ case 1:
+ FPRINTF_DEBUG_ONLY(stderr,"end_of_metadata\n");
+ decoder_valid = FLAC__stream_decoder_process_until_end_of_metadata(decoder);
+ break;
+ case 2:
+ FPRINTF_DEBUG_ONLY(stderr,"single\n");
+ decoder_valid = FLAC__stream_decoder_process_single(decoder);
+ break;
+ case 3:
+ FPRINTF_DEBUG_ONLY(stderr,"skip_single\n");
+ decoder_valid = FLAC__stream_decoder_skip_single_frame(decoder);
+ break;
+ case 4:
+ FPRINTF_DEBUG_ONLY(stderr,"reset\n");
+ decoder_valid = FLAC__stream_decoder_reset(decoder);
+ break;
+ case 5:
+ FPRINTF_DEBUG_ONLY(stderr,"flush\n");
+ decoder_valid = FLAC__stream_decoder_flush(decoder);
+ break;
+ case 6:
+ case 14:
+ shift = 1u << (command[0] >> 3);
+ FPRINTF_DEBUG_ONLY(stderr,"seek short %hhu\n",shift);
+ decoder_valid = FLAC__stream_decoder_seek_absolute(decoder,shift);
+ break;
+ case 7:
+ if(i+8 >= command_length) /* Not enough data available to do this */
+ break;
+ seekpos = ((FLAC__uint64)command[1] << 56) +
+ ((FLAC__uint64)command[2] << 48) +
+ ((FLAC__uint64)command[3] << 40) +
+ ((FLAC__uint64)command[4] << 32) +
+ ((FLAC__uint64)command[5] << 24) +
+ ((FLAC__uint64)command[6] << 16) +
+ ((FLAC__uint64)command[7] << 8) +
+ command[8];
+ i+=8;
+ FPRINTF_DEBUG_ONLY(stderr,"seek long %lu\n",seekpos);
+ decoder_valid = FLAC__stream_decoder_seek_absolute(decoder,seekpos);
+ break;
+ case 8:
+ /* Set abort on write callback */
+ write_abort_check_counter = (command[0] >> 4) + 1;
+ break;
+ }
+ }
+
+ FLAC__stream_decoder_finish(decoder);
+
+ FLAC__stream_decoder_delete(decoder);
+
+ return 0;
+}
+
diff --git a/oss-fuzz/tool_flac.c b/oss-fuzz/tool_flac.c
new file mode 100644
index 0000000..ce10a07
--- /dev/null
+++ b/oss-fuzz/tool_flac.c
@@ -0,0 +1,117 @@
+/* fuzzer_tool_flac
+ * Copyright (C) 2023 Xiph.Org Foundation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the Xiph.org Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 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 FOUNDATION 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 <stdlib.h>
+#include <string.h> /* for memcpy */
+#define FUZZ_TOOL_FLAC
+#define fprintf(...)
+#define printf(...)
+#include "../src/flac/main.c"
+#include "common.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ size_t size_left = size;
+ size_t arglen;
+ char * argv[67];
+ char exename[] = "flac";
+ char filename[] = "/tmp/fuzzXXXXXX";
+ int numarg = 0, maxarg;
+ int file_to_fuzz;
+ int tmp_stdout, tmp_stdin;
+ fpos_t pos_stdout;
+ bool use_stdin = false;
+
+ /* reset global vars */
+ flac__utils_verbosity_ = 0;
+ share__opterr = 0;
+ share__optind = 0;
+
+ if(size < 2)
+ return 0;
+
+ maxarg = data[0] & 63;
+ use_stdin = data[0] & 64;
+ size_left--;
+
+ argv[0] = exename;
+ numarg++;
+
+ /* Check whether input is zero delimited */
+ while((arglen = strnlen((char *)data+(size-size_left),size_left)) < size_left && numarg < maxarg) {
+ argv[numarg++] = (char *)data+(size-size_left);
+ size_left -= arglen + 1;
+ }
+
+ file_to_fuzz = mkstemp(filename);
+
+ if (file_to_fuzz < 0)
+ abort();
+ write(file_to_fuzz,data+(size-size_left),size_left);
+ close(file_to_fuzz);
+
+ /* redirect stdout */
+ fflush(stdout);
+ fgetpos(stdout,&pos_stdout);
+ tmp_stdout = dup(fileno(stdout));
+ freopen("/dev/null","w",stdout);
+
+ /* redirect stdin */
+ tmp_stdin = dup(fileno(stdin));
+
+ if(use_stdin)
+ freopen(filename,"r",stdin);
+ else {
+ freopen("/dev/null","r",stdin);
+ argv[numarg++] = filename;
+ }
+
+ main_to_fuzz(numarg,argv);
+
+ /* restore stdout */
+ fflush(stdout);
+ dup2(tmp_stdout, fileno(stdout));
+ close(tmp_stdout);
+ clearerr(stdout);
+ fsetpos(stdout,&pos_stdout);
+
+ /* restore stdin */
+ dup2(tmp_stdin, fileno(stdin));
+ close(tmp_stdin);
+ clearerr(stdin);
+
+ unlink(filename);
+
+ return 0;
+}
+
diff --git a/oss-fuzz/tool_metaflac.c b/oss-fuzz/tool_metaflac.c
new file mode 100644
index 0000000..a6fafa2
--- /dev/null
+++ b/oss-fuzz/tool_metaflac.c
@@ -0,0 +1,136 @@
+/* fuzzer_tool_flac
+ * Copyright (C) 2023 Xiph.Org Foundation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - 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.
+ *
+ * - Neither the name of the Xiph.org Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * 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 FOUNDATION 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* for memcpy */
+#define FUZZ_TOOL_METAFLAC
+#define fprintf(...)
+#define printf(...)
+#include "../src/metaflac/main.c"
+#include "common.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ size_t size_left = size;
+ size_t arglen;
+ char * argv[64];
+ char exename[] = "metaflac";
+ char filename[] = "/tmp/fuzzXXXXXX";
+ char filename_stdin[] = "/tmp/fuzzXXXXXX";
+ int numarg = 0, maxarg;
+ int file_to_fuzz;
+ int tmp_stdout, tmp_stdin;
+ fpos_t pos_stdout;
+ bool use_stdin = false;
+
+ share__opterr = 0;
+ share__optind = 0;
+
+
+ if(size < 2)
+ return 0;
+
+ maxarg = data[0] & 15;
+ use_stdin = data[0] & 16;
+ size_left--;
+
+ argv[0] = exename;
+ numarg++;
+
+ /* Check whether input is zero delimited */
+ while((arglen = strnlen((char *)data+(size-size_left),size_left)) < size_left && numarg < maxarg) {
+ argv[numarg++] = (char *)data+(size-size_left);
+ size_left -= arglen + 1;
+ }
+
+ /* Create file to feed directly */
+ file_to_fuzz = mkstemp(filename);
+ if (file_to_fuzz < 0)
+ abort();
+ if(use_stdin) {
+ write(file_to_fuzz,data+(size-size_left),size_left/2);
+ size_left -= size_left/2;
+ }
+ else
+ write(file_to_fuzz,data+(size-size_left),size_left);
+ close(file_to_fuzz);
+
+ argv[numarg++] = filename;
+
+ /* Create file to feed to stdin */
+ if(use_stdin) {
+ file_to_fuzz = mkstemp(filename_stdin);
+ if (file_to_fuzz < 0)
+ abort();
+ write(file_to_fuzz,data+(size-size_left),size_left);
+ close(file_to_fuzz);
+ }
+
+ /* redirect stdout */
+ fflush(stdout);
+ fgetpos(stdout,&pos_stdout);
+ tmp_stdout = dup(fileno(stdout));
+ freopen("/dev/null","w",stdout);
+
+ /* redirect stdin */
+ tmp_stdin = dup(fileno(stdin));
+ if(use_stdin)
+ freopen(filename_stdin,"r",stdin);
+ else {
+ freopen("/dev/null","r",stdin);
+ argv[numarg++] = filename;
+ }
+
+ main_to_fuzz(numarg,argv);
+
+ /* restore stdout */
+ fflush(stdout);
+ dup2(tmp_stdout, fileno(stdout));
+ close(tmp_stdout);
+ clearerr(stdout);
+ fsetpos(stdout,&pos_stdout);
+
+ /* restore stdin */
+ dup2(tmp_stdin, fileno(stdin));
+ close(tmp_stdin);
+ clearerr(stdin);
+
+ unlink(filename);
+
+ if(use_stdin)
+ unlink(filename_stdin);
+
+ return 0;
+}
+