diff options
Diffstat (limited to '')
-rw-r--r-- | oss-fuzz/Makefile.am | 104 | ||||
-rw-r--r-- | oss-fuzz/Makefile.in | 1033 | ||||
-rw-r--r-- | oss-fuzz/Readme.md | 13 | ||||
-rw-r--r-- | oss-fuzz/common.h | 2 | ||||
-rw-r--r-- | oss-fuzz/decoder.cc | 408 | ||||
-rw-r--r-- | oss-fuzz/empty.cc | 0 | ||||
-rw-r--r-- | oss-fuzz/encoder.cc | 257 | ||||
-rw-r--r-- | oss-fuzz/encoder_v2.cc | 352 | ||||
-rw-r--r-- | oss-fuzz/fuzzer_encoder.dict | 18 | ||||
-rw-r--r-- | oss-fuzz/fuzzing/datasource/datasource.hpp | 190 | ||||
-rw-r--r-- | oss-fuzz/fuzzing/datasource/id.hpp | 75 | ||||
-rw-r--r-- | oss-fuzz/fuzzing/exception.hpp | 67 | ||||
-rw-r--r-- | oss-fuzz/fuzzing/memory.hpp | 96 | ||||
-rw-r--r-- | oss-fuzz/fuzzing/types.hpp | 158 | ||||
-rw-r--r-- | oss-fuzz/metadata.cc | 526 | ||||
-rw-r--r-- | oss-fuzz/reencoder.cc | 304 | ||||
-rw-r--r-- | oss-fuzz/seek.cc | 195 | ||||
-rw-r--r-- | oss-fuzz/tool_flac.c | 117 | ||||
-rw-r--r-- | oss-fuzz/tool_metaflac.c | 136 |
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; +} + |