diff options
Diffstat (limited to 'src/flac')
-rw-r--r-- | src/flac/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/flac/Makefile.am | 22 | ||||
-rw-r--r-- | src/flac/analyze.c | 5 | ||||
-rw-r--r-- | src/flac/analyze.h | 2 | ||||
-rw-r--r-- | src/flac/decode.c | 43 | ||||
-rw-r--r-- | src/flac/decode.h | 2 | ||||
-rw-r--r-- | src/flac/encode.c | 208 | ||||
-rw-r--r-- | src/flac/encode.h | 6 | ||||
-rw-r--r-- | src/flac/foreign_metadata.c | 9 | ||||
-rw-r--r-- | src/flac/foreign_metadata.h | 2 | ||||
-rw-r--r-- | src/flac/iffscan.c | 2 | ||||
-rw-r--r-- | src/flac/local_string_utils.h | 2 | ||||
-rw-r--r-- | src/flac/main.c | 76 | ||||
-rw-r--r-- | src/flac/utils.c | 26 | ||||
-rw-r--r-- | src/flac/utils.h | 4 | ||||
-rw-r--r-- | src/flac/version.rc | 38 | ||||
-rw-r--r-- | src/flac/vorbiscomment.c | 2 | ||||
-rw-r--r-- | src/flac/vorbiscomment.h | 2 |
18 files changed, 208 insertions, 244 deletions
diff --git a/src/flac/CMakeLists.txt b/src/flac/CMakeLists.txt index 40034502..da7ce8de 100644 --- a/src/flac/CMakeLists.txt +++ b/src/flac/CMakeLists.txt @@ -10,6 +10,7 @@ add_executable(flacapp local_string_utils.c utils.c vorbiscomment.c + version.rc $<$<BOOL:${WIN32}>:../../include/share/win_utf8_io.h> $<$<BOOL:${WIN32}>:../share/win_utf8_io/win_utf8_io.c>) set_property(TARGET flacapp PROPERTY RUNTIME_OUTPUT_NAME flac) diff --git a/src/flac/Makefile.am b/src/flac/Makefile.am index 5fc34386..279a7cb9 100644 --- a/src/flac/Makefile.am +++ b/src/flac/Makefile.am @@ -1,6 +1,6 @@ # flac - Command-line FLAC encoder/decoder # Copyright (C) 2000-2009 Josh Coalson -# Copyright (C) 2011-2022 Xiph.Org Foundation +# Copyright (C) 2011-2023 Xiph.Org Foundation # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -16,13 +16,22 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +if OS_IS_WINDOWS +win_utf8_lib = $(top_builddir)/src/share/win_utf8_io/libwin_utf8_io.la +if HAVE_WINDRES +flac_DEPENDENCIES = version.o +windows_resource_link = -Wl,version.o +endif +endif + bin_PROGRAMS = flac AM_CFLAGS = @OGG_CFLAGS@ AM_CPPFLAGS = -I$(top_builddir) -I$(srcdir)/include -I$(top_srcdir)/include EXTRA_DIST = \ CMakeLists.txt \ - iffscan.c + iffscan.c \ + version.rc flac_SOURCES = \ analyze.c \ @@ -41,10 +50,6 @@ flac_SOURCES = \ utils.h \ vorbiscomment.h -if OS_IS_WINDOWS -win_utf8_lib = $(top_builddir)/src/share/win_utf8_io/libwin_utf8_io.la -endif - flac_LDADD = \ $(top_builddir)/src/share/utf8/libutf8.la \ $(top_builddir)/src/share/grabbag/libgrabbag.la \ @@ -56,4 +61,9 @@ flac_LDADD = \ @LTLIBICONV@ \ -lm +flac_LDFLAGS = $(AM_LDFLAGS) $(windows_resource_link) + CLEANFILES = flac.exe + +.rc.o: + $(RC) $(AM_CPPFLAGS) $< $@ diff --git a/src/flac/analyze.c b/src/flac/analyze.c index ff1b170d..0a85565e 100644 --- a/src/flac/analyze.c +++ b/src/flac/analyze.c @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -245,5 +245,8 @@ FLAC__bool dump_stats(const subframe_stats_t *stats, const char *filename) fprintf(outfile, "pause -1 'waiting...'\n"); fclose(outfile); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + unlink(filename); +#endif return true; } diff --git a/src/flac/analyze.h b/src/flac/analyze.h index fbdec29e..ce07b145 100644 --- a/src/flac/analyze.h +++ b/src/flac/analyze.h @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/flac/decode.c b/src/flac/decode.c index c9c74546..90f7a6c8 100644 --- a/src/flac/decode.c +++ b/src/flac/decode.c @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -242,7 +242,7 @@ FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__ d->has_md5sum = false; d->bps = 0; d->channels = 0; - d->sample_rate = 0; + d->sample_rate = UINT32_MAX; d->channel_mask = 0; d->decode_position = 0; @@ -297,7 +297,11 @@ void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred) } #endif fclose(d->fout); + +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + /* Always delete output file when fuzzing */ if(error_occurred) +#endif flac_unlink(d->outfilename); } } @@ -586,7 +590,10 @@ int DecoderSession_finish_error(DecoderSession *d) FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, uint32_t sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input) { /* convert from mm:ss.sss to sample number if necessary */ - flac__utils_canonicalize_skip_until_specification(spec, sample_rate); + if(!flac__utils_canonicalize_skip_until_specification(spec, sample_rate)) { + flac__utils_printf(stderr, 1, "%s: ERROR, value of --until is too large\n", inbasefilename); + return false; + } /* special case: if "--until=-0", use the special value '0' to mean "end-of-stream" */ if(spec->is_relative && spec->value.samples == 0) { @@ -707,7 +714,7 @@ FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uin else if(format == FORMAT_AIFF) iff_size = 46 + foreign_metadata_size + aligned_data_size; else /* AIFF-C */ - iff_size = 16 + foreign_metadata_size + aligned_data_size + fm->aifc_comm_length; + iff_size = 16 + foreign_metadata_size + aligned_data_size + (fm?fm->aifc_comm_length:0); if(format != FORMAT_WAVE64 && format != FORMAT_RF64 && iff_size >= 0xFFFFFFF4) { flac__utils_printf(stderr, 1, "%s: ERROR: stream is too big to fit in a single %s file\n", decoder_session->inbasefilename, fmt_desc); @@ -1095,7 +1102,7 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder DecoderSession *decoder_session = (DecoderSession*)client_data; FILE *fout = decoder_session->fout; const uint32_t bps = frame->header.bits_per_sample, channels = frame->header.channels; - const uint32_t shift = (decoder_session->format != FORMAT_RAW && (bps%8))? 8-(bps%8): 0; + const uint32_t shift = (bps%8)? 8-(bps%8): 0; FLAC__bool is_big_endian = ( (decoder_session->format == FORMAT_AIFF || (decoder_session->format == FORMAT_AIFF_C && decoder_session->subformat == SUBFORMAT_AIFF_C_NONE)) ? true : ( decoder_session->format == FORMAT_WAVE || decoder_session->format == FORMAT_WAVE64 || decoder_session->format == FORMAT_RF64 || (decoder_session->format == FORMAT_AIFF_C && decoder_session->subformat == SUBFORMAT_AIFF_C_SOWT) ? false : @@ -1140,6 +1147,10 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder else { /* must not have gotten STREAMINFO, save the bps from the frame header */ FLAC__ASSERT(!decoder_session->got_stream_info); + if(decoder_session->format == FORMAT_RAW && ((decoder_session->bps % 8) != 0 || decoder_session->bps < 4)) { + flac__utils_printf(stderr, 1, "%s: ERROR: bits per sample is %u, must be 8/16/24/32 for raw format output\n", decoder_session->inbasefilename, decoder_session->bps); + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } decoder_session->bps = bps; } @@ -1161,7 +1172,7 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder } /* sanity-check the sample rate */ - if(!decoder_session->got_stream_info) { + if(decoder_session->sample_rate < UINT32_MAX) { if(frame->header.sample_rate != decoder_session->sample_rate) { if(decoder_session->got_stream_info) flac__utils_printf(stderr, 1, "%s: ERROR, sample rate is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, frame->header.sample_rate, decoder_session->sample_rate); @@ -1172,15 +1183,16 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder } } else { + /* must not have gotten STREAMINFO, save the sample rate from the frame header */ + FLAC__ASSERT(!decoder_session->got_stream_info); decoder_session->sample_rate = frame->header.sample_rate; } /* * limit the number of samples to accept based on --until */ - FLAC__ASSERT(!decoder_session->skip_specification->is_relative); /* if we never got the total_samples from the metadata, the skip and until specs would never have been canonicalized, so protect against that: */ - if(decoder_session->skip_specification->is_relative) { + if(decoder_session->skip_specification->is_relative || !decoder_session->got_stream_info) { if(decoder_session->skip_specification->value.samples == 0) /* special case for when no --skip was given */ decoder_session->skip_specification->is_relative = false; /* convert to our meaning of beginning-of-stream */ else { @@ -1188,7 +1200,7 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } } - if(decoder_session->until_specification->is_relative) { + if(decoder_session->until_specification->is_relative || !decoder_session->got_stream_info) { if(decoder_session->until_specification->value.samples == 0) /* special case for when no --until was given */ decoder_session->until_specification->is_relative = false; /* convert to our meaning of end-of-stream */ else { @@ -1452,7 +1464,11 @@ void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMet decoder_session->channels = metadata->data.stream_info.channels; decoder_session->sample_rate = metadata->data.stream_info.sample_rate; - flac__utils_canonicalize_skip_until_specification(decoder_session->skip_specification, decoder_session->sample_rate); + if(!flac__utils_canonicalize_skip_until_specification(decoder_session->skip_specification, decoder_session->sample_rate)) { + flac__utils_printf(stderr, 1, "%s: ERROR, value of --skip is too large\n", decoder_session->inbasefilename); + decoder_session->abort_flag = true; + return; + } FLAC__ASSERT(decoder_session->skip_specification->value.samples >= 0); skip = (FLAC__uint64)decoder_session->skip_specification->value.samples; @@ -1529,6 +1545,13 @@ void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMet return; } } + else if(decoder_session->bps == 0) { + flac__utils_printf(stderr, 1, "%s: WARNING: can't apply ReplayGain, bit-per-sample value is invalid\n", decoder_session->inbasefilename); + if(decoder_session->treat_warnings_as_errors) { + decoder_session->abort_flag = true; + return; + } + } else { const char *ls[] = { "no", "peak", "hard" }; const char *ns[] = { "no", "low", "medium", "high" }; diff --git a/src/flac/decode.h b/src/flac/decode.h index 67bd3c04..24f5723d 100644 --- a/src/flac/decode.h +++ b/src/flac/decode.h @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/flac/encode.c b/src/flac/encode.c index bc71088d..a945b356 100644 --- a/src/flac/encode.c +++ b/src/flac/encode.c @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -47,7 +47,6 @@ #endif #define max(x,y) ((x)>(y)?(x):(y)) -/* this MUST be >= 588 so that sector aligning can take place with one read */ /* this MUST be < 2^sizeof(size_t) / ( FLAC__MAX_CHANNELS * (FLAC__MAX_BITS_PER_SAMPLE/8) ) */ #define CHUNK_OF_SAMPLES 2048 @@ -143,7 +142,7 @@ static FLAC__int32 *input_[FLAC__MAX_CHANNELS]; */ static FLAC__bool EncoderSession_construct(EncoderSession *e, encode_options_t options, FLAC__off_t infilesize, FILE *infile, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, uint32_t lookahead_length); static void EncoderSession_destroy(EncoderSession *e); -static int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_align_zero, foreign_metadata_t *foreign_metadata, FLAC__bool error_on_compression_fail); +static int EncoderSession_finish_ok(EncoderSession *e, foreign_metadata_t *foreign_metadata, FLAC__bool error_on_compression_fail); static int EncoderSession_finish_error(EncoderSession *e); static FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options); static FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const buffer[], uint32_t samples); @@ -327,7 +326,7 @@ static FLAC__bool get_sample_info_wave(EncoderSession *e, encode_options_t optio } data_bytes -= (16+8); } - if(data_bytes < 16) { + if(data_bytes < 16 || data_bytes > (UINT32_MAX-8)) { flac__utils_printf(stderr, 1, "%s: ERROR: non-standard 'fmt ' chunk has length = %u\n", e->inbasefilename, (uint32_t)data_bytes); return false; } @@ -482,7 +481,6 @@ static FLAC__bool get_sample_info_wave(EncoderSession *e, encode_options_t optio data_bytes = ds64_data_size; } if(options.ignore_chunk_sizes) { - FLAC__ASSERT(!options.sector_align); if(data_bytes) { flac__utils_printf(stderr, 1, "%s: WARNING: 'data' chunk has non-zero size, using --ignore-chunk-sizes is probably a bad idea\n", e->inbasefilename, chunk_id); if(e->treat_warnings_as_errors) @@ -717,7 +715,6 @@ static FLAC__bool get_sample_info_aiff(EncoderSession *e, encode_options_t optio return false; data_bytes = xx; if(options.ignore_chunk_sizes) { - FLAC__ASSERT(!options.sector_align); if(data_bytes) { flac__utils_printf(stderr, 1, "%s: WARNING: 'SSND' chunk has non-zero size, using --ignore-chunk-sizes is probably a bad idea\n", e->inbasefilename, chunk_id); if(e->treat_warnings_as_errors) @@ -864,7 +861,6 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena { EncoderSession encoder_session; size_t channel_map[FLAC__MAX_CHANNELS]; - int info_align_carry = -1, info_align_zero = -1; if(!EncoderSession_construct(&encoder_session, options, infilesize, infile, infilename, outfilename, lookahead, lookahead_length)) return 1; @@ -946,34 +942,19 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena flac__utils_printf(stderr, 1, "%s: ERROR: unsupported bits-per-sample %u\n", encoder_session.inbasefilename, encoder_session.info.bits_per_sample-encoder_session.info.shift); return EncoderSession_finish_error(&encoder_session); } - if(options.sector_align) { - if(encoder_session.info.channels != 2) { - flac__utils_printf(stderr, 1, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, encoder_session.info.channels); - return EncoderSession_finish_error(&encoder_session); - } - if(encoder_session.info.sample_rate != 44100) { - flac__utils_printf(stderr, 1, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, encoder_session.info.sample_rate); - return EncoderSession_finish_error(&encoder_session); - } - if(encoder_session.info.bits_per_sample-encoder_session.info.shift != 16) { - flac__utils_printf(stderr, 1, "%s: ERROR: file has %u bits-per-sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, encoder_session.info.bits_per_sample-encoder_session.info.shift); - return EncoderSession_finish_error(&encoder_session); - } - } { FLAC__uint64 total_samples_in_input; /* WATCHOUT: may be 0 to mean "unknown" */ FLAC__uint64 skip; FLAC__uint64 until; /* a value of 0 mean end-of-stream (i.e. --until=-0) */ uint32_t consecutive_eos_count = 0; - uint32_t align_remainder = 0; switch(options.format) { case FORMAT_RAW: if(infilesize < 0) total_samples_in_input = 0; else - total_samples_in_input = (FLAC__uint64)infilesize / encoder_session.info.bytes_per_wide_sample + *options.align_reservoir_samples; + total_samples_in_input = (FLAC__uint64)infilesize / encoder_session.info.bytes_per_wide_sample; break; case FORMAT_WAVE: case FORMAT_WAVE64: @@ -981,7 +962,7 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena case FORMAT_AIFF: case FORMAT_AIFF_C: /* truncation in the division removes any padding byte that was counted in encoder_session.fmt.iff.data_bytes */ - total_samples_in_input = encoder_session.fmt.iff.data_bytes / encoder_session.info.bytes_per_wide_sample + *options.align_reservoir_samples; + total_samples_in_input = encoder_session.fmt.iff.data_bytes / encoder_session.info.bytes_per_wide_sample; /* check for chunks trailing the audio data */ if(!options.ignore_chunk_sizes && !options.format_options.iff.foreign_metadata @@ -1004,7 +985,7 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena break; case FORMAT_FLAC: case FORMAT_OGGFLAC: - total_samples_in_input = encoder_session.fmt.flac.client_data.metadata_blocks[0]->data.stream_info.total_samples + *options.align_reservoir_samples; + total_samples_in_input = encoder_session.fmt.flac.client_data.metadata_blocks[0]->data.stream_info.total_samples; break; default: FLAC__ASSERT(0); @@ -1016,12 +997,12 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena * now that we know the sample rate, canonicalize the * --skip string to an absolute sample number: */ - flac__utils_canonicalize_skip_until_specification(&options.skip_specification, encoder_session.info.sample_rate); + if(!flac__utils_canonicalize_skip_until_specification(&options.skip_specification, encoder_session.info.sample_rate)) { + flac__utils_printf(stderr, 1, "%s: ERROR: value of --skip is too large\n", encoder_session.inbasefilename, encoder_session.info.bits_per_sample-encoder_session.info.shift); + return EncoderSession_finish_error(&encoder_session); + } FLAC__ASSERT(options.skip_specification.value.samples >= 0); skip = (FLAC__uint64)options.skip_specification.value.samples; - FLAC__ASSERT(!options.sector_align || (options.format != FORMAT_FLAC && options.format != FORMAT_OGGFLAC && skip == 0)); - /* *options.align_reservoir_samples will be 0 unless --sector-align is used */ - FLAC__ASSERT(options.sector_align || *options.align_reservoir_samples == 0); /* * now that we possibly know the input size, canonicalize the @@ -1030,11 +1011,15 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena if(!canonicalize_until_specification(&options.until_specification, encoder_session.inbasefilename, encoder_session.info.sample_rate, skip, total_samples_in_input)) return EncoderSession_finish_error(&encoder_session); until = (FLAC__uint64)options.until_specification.value.samples; - FLAC__ASSERT(!options.sector_align || until == 0); /* adjust encoding parameters based on skip and until values */ switch(options.format) { case FORMAT_RAW: + FLAC__ASSERT(sizeof(FLAC__off_t) == 8); + if(skip >= INT64_MAX / encoder_session.info.bytes_per_wide_sample) { + flac__utils_printf(stderr, 1, "%s: ERROR: value of --skip is too large\n", encoder_session.inbasefilename, encoder_session.info.bits_per_sample-encoder_session.info.shift); + return EncoderSession_finish_error(&encoder_session); + } infilesize -= (FLAC__off_t)skip * encoder_session.info.bytes_per_wide_sample; encoder_session.total_samples_to_encode = total_samples_in_input - skip; break; @@ -1043,6 +1028,11 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena case FORMAT_RF64: case FORMAT_AIFF: case FORMAT_AIFF_C: + FLAC__ASSERT(sizeof(FLAC__off_t) == 8); + if(skip >= INT64_MAX / encoder_session.info.bytes_per_wide_sample) { + flac__utils_printf(stderr, 1, "%s: ERROR: value of --skip is too large\n", encoder_session.inbasefilename, encoder_session.info.bits_per_sample-encoder_session.info.shift); + return EncoderSession_finish_error(&encoder_session); + } encoder_session.fmt.iff.data_bytes -= skip * encoder_session.info.bytes_per_wide_sample; if(options.ignore_chunk_sizes) { encoder_session.total_samples_to_encode = 0; @@ -1064,21 +1054,12 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena if(until > 0) { const FLAC__uint64 trim = total_samples_in_input - until; FLAC__ASSERT(total_samples_in_input > 0); - FLAC__ASSERT(!options.sector_align); if(options.format == FORMAT_RAW) infilesize -= (FLAC__off_t)trim * encoder_session.info.bytes_per_wide_sample; else if(EncoderSession_format_is_iff(&encoder_session)) encoder_session.fmt.iff.data_bytes -= trim * encoder_session.info.bytes_per_wide_sample; encoder_session.total_samples_to_encode -= trim; } - if(options.sector_align && (options.format != FORMAT_RAW || infilesize >=0)) { /* for RAW, need to know the filesize */ - FLAC__ASSERT(skip == 0); /* asserted above too, but lest we forget */ - align_remainder = (uint32_t)(encoder_session.total_samples_to_encode % 588); - if(options.is_last_file) - encoder_session.total_samples_to_encode += (588-align_remainder); /* will pad with zeroes */ - else - encoder_session.total_samples_to_encode -= align_remainder; /* will stop short and carry over to next file */ - } switch(options.format) { case FORMAT_RAW: encoder_session.unencoded_size = encoder_session.total_samples_to_encode * encoder_session.info.bytes_per_wide_sample; @@ -1183,36 +1164,6 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena } /* - * first do any samples in the reservoir - */ - if(options.sector_align && *options.align_reservoir_samples > 0) { - FLAC__ASSERT(options.format != FORMAT_FLAC && options.format != FORMAT_OGGFLAC); /* check again */ - if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)options.align_reservoir, *options.align_reservoir_samples)) { - print_error_with_state(&encoder_session, "ERROR during encoding"); - return EncoderSession_finish_error(&encoder_session); - } - } - - /* - * decrement infilesize or the data_bytes counter if we need to align the file - */ - if(options.sector_align) { - if(options.is_last_file) { - *options.align_reservoir_samples = 0; - } - else { - *options.align_reservoir_samples = align_remainder; - if(options.format == FORMAT_RAW) { - FLAC__ASSERT(infilesize >= 0); - infilesize -= (FLAC__off_t)((*options.align_reservoir_samples) * encoder_session.info.bytes_per_wide_sample); - FLAC__ASSERT(infilesize >= 0); - } - else if(EncoderSession_format_is_iff(&encoder_session)) - encoder_session.fmt.iff.data_bytes -= (*options.align_reservoir_samples) * encoder_session.info.bytes_per_wide_sample; - } - } - - /* * now do samples from the file */ switch(options.format) { @@ -1265,10 +1216,18 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena wanted = (size_t) min((FLAC__uint64)wanted, max_input_bytes - total_input_bytes_read); if(lookahead_length > 0) { - FLAC__ASSERT(lookahead_length <= wanted); - memcpy(ubuffer.u8, lookahead, lookahead_length); - wanted -= lookahead_length; - bytes_read = lookahead_length; + if(lookahead_length <= wanted) { + memcpy(ubuffer.u8, lookahead, lookahead_length); + wanted -= lookahead_length; + bytes_read = lookahead_length; + } + else { + /* This happens when --until is used on a very short file */ + FLAC__ASSERT(lookahead_length < CHUNK_OF_SAMPLES * encoder_session.info.bytes_per_wide_sample); + memcpy(ubuffer.u8, lookahead, wanted); + wanted = 0; + bytes_read = wanted; + } if(wanted > 0) { bytes_read += fread(ubuffer.u8+lookahead_length, sizeof(uint8_t), wanted, infile); if(ferror(infile)) { @@ -1382,7 +1341,7 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena break; } - if(!FLAC__stream_decoder_process_single(encoder_session.fmt.flac.decoder)) { + if(decoder_state == FLAC__STREAM_DECODER_ABORTED || !FLAC__stream_decoder_process_single(encoder_session.fmt.flac.decoder)) { flac__utils_printf(stderr, 1, "%s: ERROR: while decoding FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__stream_decoder_get_resolved_state_string(encoder_session.fmt.flac.decoder)); return EncoderSession_finish_error(&encoder_session); } @@ -1398,53 +1357,10 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena return EncoderSession_finish_error(&encoder_session); } - /* - * now read unaligned samples into reservoir or pad with zeroes if necessary - */ - if(options.sector_align) { - if(options.is_last_file) { - uint32_t wide_samples = 588 - align_remainder; - if(wide_samples < 588) { - uint32_t channel; - - info_align_zero = wide_samples; - for(channel = 0; channel < encoder_session.info.channels; channel++) - memset(input_[channel], 0, sizeof(input_[0][0]) * wide_samples); - - if(!EncoderSession_process(&encoder_session, (const FLAC__int32 * const *)input_, wide_samples)) { - print_error_with_state(&encoder_session, "ERROR during encoding"); - return EncoderSession_finish_error(&encoder_session); - } - } - } - else { - if(*options.align_reservoir_samples > 0) { - size_t bytes_read; - FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588); - bytes_read = fread(ubuffer.u8, sizeof(uint8_t), (*options.align_reservoir_samples) * encoder_session.info.bytes_per_wide_sample, infile); - if(bytes_read == 0 && ferror(infile)) { - flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); - return EncoderSession_finish_error(&encoder_session); - } - else if(bytes_read != (*options.align_reservoir_samples) * encoder_session.info.bytes_per_wide_sample) { - flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; read %" PRIu64 " bytes; expected %" PRIu64 " samples, got %" PRIu64 " samples\n", encoder_session.inbasefilename, bytes_read, encoder_session.total_samples_to_encode, encoder_session.samples_written); - if(encoder_session.treat_warnings_as_errors) - return EncoderSession_finish_error(&encoder_session); - } - else { - info_align_carry = *options.align_reservoir_samples; - if(!format_input(options.align_reservoir, *options.align_reservoir_samples, encoder_session.info.is_big_endian, encoder_session.info.is_unsigned_samples, encoder_session.info.channels, encoder_session.info.bits_per_sample, encoder_session.info.shift, channel_map)) - return EncoderSession_finish_error(&encoder_session); - } - } - } - } } return EncoderSession_finish_ok( &encoder_session, - info_align_carry, - info_align_zero, EncoderSession_format_is_iff(&encoder_session)? options.format_options.iff.foreign_metadata : 0, options.error_on_compression_fail ); @@ -1520,7 +1436,9 @@ FLAC__bool EncoderSession_construct(EncoderSession *e, encode_options_t options, e->fmt.flac.client_data.fatal_error = false; break; default: +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION FLAC__ASSERT(0); +#endif /* double protection */ return false; } @@ -1571,7 +1489,7 @@ void EncoderSession_destroy(EncoderSession *e) } } -int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_align_zero, foreign_metadata_t *foreign_metadata, FLAC__bool error_on_compression_fail) +int EncoderSession_finish_ok(EncoderSession *e, foreign_metadata_t *foreign_metadata, FLAC__bool error_on_compression_fail) { FLAC__StreamEncoderState fse_state = FLAC__STREAM_ENCODER_OK; int ret = 0; @@ -1597,14 +1515,6 @@ int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_a print_verify_error(e); ret = 1; } - else { - if(info_align_carry >= 0) { - flac__utils_printf(stderr, 1, "%s: INFO: sector alignment causing %d samples to be carried over\n", e->inbasefilename, info_align_carry); - } - if(info_align_zero >= 0) { - flac__utils_printf(stderr, 1, "%s: INFO: sector alignment causing %d zero samples to be appended\n", e->inbasefilename, info_align_zero); - } - } /*@@@@@@ should this go here or somewhere else? */ if(ret == 0 && foreign_metadata) { @@ -1626,6 +1536,11 @@ int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_a ret = 1; } +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + /* Always delete output file when fuzzing */ + flac_unlink(e->outfilename); +#endif + EncoderSession_destroy(e); return ret; @@ -1951,8 +1866,12 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio flac_decoder_data->num_metadata_blocks = j; if(options.padding > 0) p = options.padding; - if(p < 0) - p = e->total_samples_to_encode / sample_rate < 20*60? FLAC_ENCODE__DEFAULT_PADDING : FLAC_ENCODE__DEFAULT_PADDING*8; + if(p < 0) { + if(sample_rate == 0) + p = FLAC_ENCODE__DEFAULT_PADDING; + else + p = e->total_samples_to_encode / sample_rate < 20*60? FLAC_ENCODE__DEFAULT_PADDING : FLAC_ENCODE__DEFAULT_PADDING*8; + } if(p > 0) p += (e->replay_gain ? GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED : 0); p = min(p, (int)((1u << FLAC__STREAM_METADATA_LENGTH_LEN) - 1)); @@ -2015,7 +1934,10 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio if(options.padding != 0) { padding.is_last = false; /* the encoder will set this for us */ padding.type = FLAC__METADATA_TYPE_PADDING; - padding.length = (uint32_t)(options.padding>0? options.padding : (e->total_samples_to_encode / sample_rate < 20*60? FLAC_ENCODE__DEFAULT_PADDING : FLAC_ENCODE__DEFAULT_PADDING*8)) + (e->replay_gain ? GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED : 0); + if(sample_rate == 0) + padding.length = (uint32_t)(options.padding>0? options.padding : FLAC_ENCODE__DEFAULT_PADDING) + (e->replay_gain ? GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED : 0); + else + padding.length = (uint32_t)(options.padding>0? options.padding : (e->total_samples_to_encode / sample_rate < 20*60? FLAC_ENCODE__DEFAULT_PADDING : FLAC_ENCODE__DEFAULT_PADDING*8)) + (e->replay_gain ? GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED : 0); padding.length = min(padding.length, (1u << FLAC__STREAM_METADATA_LENGTH_LEN) - 1); static_metadata_append(&static_metadata, &padding, /*needs_delete=*/false); } @@ -2065,19 +1987,25 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio } break; case CST_MAX_LPC_ORDER: +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION FLAC__stream_encoder_set_max_lpc_order(e->encoder, options.compression_settings[ic].value.t_unsigned); +#endif break; case CST_QLP_COEFF_PRECISION: FLAC__stream_encoder_set_qlp_coeff_precision(e->encoder, options.compression_settings[ic].value.t_unsigned); break; case CST_DO_QLP_COEFF_PREC_SEARCH: +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION FLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder, options.compression_settings[ic].value.t_bool); +#endif break; case CST_DO_ESCAPE_CODING: FLAC__stream_encoder_set_do_escape_coding(e->encoder, options.compression_settings[ic].value.t_bool); break; case CST_DO_EXHAUSTIVE_MODEL_SEARCH: +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION FLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder, options.compression_settings[ic].value.t_bool); +#endif break; case CST_MIN_RESIDUAL_PARTITION_ORDER: FLAC__stream_encoder_set_min_residual_partition_order(e->encoder, options.compression_settings[ic].value.t_unsigned); @@ -2090,8 +2018,10 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio break; } } +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if(*apodizations) FLAC__stream_encoder_set_apodization(e->encoder, apodizations); +#endif FLAC__stream_encoder_set_total_samples_estimate(e->encoder, e->total_samples_to_encode); FLAC__stream_encoder_set_metadata(e->encoder, (num_metadata > 0)? metadata : 0, num_metadata); FLAC__stream_encoder_set_limit_min_bitrate(e->encoder, options.limit_min_bitrate); @@ -2180,14 +2110,13 @@ FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int if(num_requested_seek_points == 0 && 0 == cuesheet) return true; - if(num_requested_seek_points < 0) { #if FLAC__HAS_OGG - /*@@@@@@ workaround ogg bug: too many seekpoints makes table not fit in one page */ - if(e->use_ogg && e->total_samples_to_encode > 0 && e->total_samples_to_encode / e->info.sample_rate / 10 > 230) - requested_seek_points = "230x;"; - else + if(e->use_ogg) + return true; #endif - requested_seek_points = "10s;"; + + if(num_requested_seek_points < 0) { + requested_seek_points = "10s;"; num_requested_seek_points = 1; } @@ -2226,7 +2155,10 @@ FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, uint32_t sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input) { /* convert from mm:ss.sss to sample number if necessary */ - flac__utils_canonicalize_skip_until_specification(spec, sample_rate); + if(!flac__utils_canonicalize_skip_until_specification(spec, sample_rate)) { + flac__utils_printf(stderr, 1, "%s: ERROR, value of --until is too large\n", inbasefilename); + return false; + } /* special case: if "--until=-0", use the special value '0' to mean "end-of-stream" */ if(spec->is_relative && spec->value.samples == 0) { @@ -2390,7 +2322,7 @@ FLAC__bool format_input(FLAC__int32 *dest[], uint32_t wide_samples, FLAC__bool i uint32_t t; t = ubuffer.u8[b]; t |= (uint32_t)(ubuffer.u8[b+1]) << 8; - t |= (int32_t)(ubuffer.s8[b+2]) << 16; + t |= (uint32_t)((int32_t)(ubuffer.s8[b+2])) << 16; out[channel][wide_sample] = t; b += 3*channels; } @@ -2876,7 +2808,7 @@ FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, const char *fn) return false; e = ((FLAC__uint16)(buf[0])<<8 | (FLAC__uint16)(buf[1]))-0x3FFF; shift = 63-e; - if((buf[0]>>7)==1U || e<0 || e>63) { + if((buf[0]>>7)==1U || e<0 || e>=63) { flac__utils_printf(stderr, 1, "%s: ERROR: invalid floating-point value\n", fn); return false; } diff --git a/src/flac/encode.h b/src/flac/encode.h index 5cb2cb78..2d65c506 100644 --- a/src/flac/encode.h +++ b/src/flac/encode.h @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -76,14 +76,10 @@ typedef struct { FLAC__bool cued_seekpoints; FLAC__bool channel_map_none; /* --channel-map=none specified, eventually will expand to take actual channel map */ - /* options related to --replay-gain and --sector-align */ FLAC__bool is_first_file; FLAC__bool is_last_file; - FLAC__int32 **align_reservoir; - unsigned *align_reservoir_samples; FLAC__bool replay_gain; FLAC__bool ignore_chunk_sizes; - FLAC__bool sector_align; FLAC__bool error_on_compression_fail; FLAC__bool limit_min_bitrate; FLAC__bool relaxed_foreign_metadata_handling; diff --git a/src/flac/foreign_metadata.c b/src/flac/foreign_metadata.c index 63f982cc..f63fc3e6 100644 --- a/src/flac/foreign_metadata.c +++ b/src/flac/foreign_metadata.c @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -99,7 +99,12 @@ static FLAC__bool compare_data_(FILE *fin, FILE *fout, size_t size, const char * static FLAC__bool append_block_(foreign_metadata_t *fm, FLAC__off_t offset, FLAC__uint32 size, const char **error) { - foreign_block_t *fb = safe_realloc_nofree_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/); + foreign_block_t *fb; + if(size >= ((1u << FLAC__STREAM_METADATA_LENGTH_LEN) - FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8)) { + if(error) *error = "found foreign metadata chunk is too large (max is 16MiB per chunk)"; + return false; + } + fb = safe_realloc_nofree_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/); if(fb) { fb[fm->num_blocks].offset = offset; fb[fm->num_blocks].size = size; diff --git a/src/flac/foreign_metadata.h b/src/flac/foreign_metadata.h index 83d8e81f..fa68d46f 100644 --- a/src/flac/foreign_metadata.h +++ b/src/flac/foreign_metadata.h @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/flac/iffscan.c b/src/flac/iffscan.c index 5b868fd1..a5472e0c 100644 --- a/src/flac/iffscan.c +++ b/src/flac/iffscan.c @@ -1,6 +1,6 @@ /* iffscan - Simple AIFF/RIFF chunk scanner * Copyright (C) 2007-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/flac/local_string_utils.h b/src/flac/local_string_utils.h index e869d701..01f891f7 100644 --- a/src/flac/local_string_utils.h +++ b/src/flac/local_string_utils.h @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2002-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/flac/main.c b/src/flac/main.c index 56c2dfc4..c22e602c 100644 --- a/src/flac/main.c +++ b/src/flac/main.c @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -151,7 +151,6 @@ static struct share__option long_options_[] = { { "lax" , share__no_argument, 0, 0 }, { "replay-gain" , share__no_argument, 0, 0 }, { "ignore-chunk-sizes" , share__no_argument, 0, 0 }, - { "sector-align" , share__no_argument, 0, 0 }, /* DEPRECATED */ { "seekpoint" , share__required_argument, 0, 'S' }, { "padding" , share__required_argument, 0, 'P' }, #if FLAC__HAS_OGG @@ -194,7 +193,6 @@ static struct share__option long_options_[] = { { "no-keep-foreign-metadata" , share__no_argument, 0, 0 }, { "no-replay-gain" , share__no_argument, 0, 0 }, { "no-ignore-chunk-sizes" , share__no_argument, 0, 0 }, - { "no-sector-align" , share__no_argument, 0, 0 }, /* DEPRECATED */ { "no-utf8-convert" , share__no_argument, 0, 0 }, { "no-lax" , share__no_argument, 0, 0 }, #if FLAC__HAS_OGG @@ -257,7 +255,6 @@ static struct { FLAC__bool keep_foreign_metadata_if_present; FLAC__bool replay_gain; FLAC__bool ignore_chunk_sizes; - FLAC__bool sector_align; FLAC__bool utf8_convert; /* true by default, to convert tag strings from locale to utf-8, false if --no-utf8-convert used */ const char *cmdline_forced_outfilename; const char *output_prefix; @@ -302,10 +299,6 @@ static struct { * miscellaneous globals */ -static FLAC__int32 align_reservoir_0[588], align_reservoir_1[588]; /* for carrying over samples from --sector-align */ /* DEPRECATED */ -static FLAC__int32 *align_reservoir[2] = { align_reservoir_0, align_reservoir_1 }; -static uint32_t align_reservoir_samples = 0; /* 0 .. 587 */ - #ifndef FUZZ_TOOL_FLAC int main(int argc, char *argv[]) @@ -441,8 +434,6 @@ int do_it(void) if(option_values.ignore_chunk_sizes) { if(option_values.mode_decode) return usage_error("ERROR: --ignore-chunk-sizes only allowed for encoding\n"); - if(0 != option_values.sector_align) - return usage_error("ERROR: --ignore-chunk-sizes not allowed with --sector-align\n"); if(0 != option_values.until_specification) return usage_error("ERROR: --ignore-chunk-sizes not allowed with --until\n"); if(0 != option_values.cue_specification) @@ -450,22 +441,6 @@ int do_it(void) if(0 != option_values.cuesheet_filename) return usage_error("ERROR: --ignore-chunk-sizes not allowed with --cuesheet\n"); } - if(option_values.sector_align) { - if(option_values.mode_decode) - return usage_error("ERROR: --sector-align only allowed for encoding\n"); - if(0 != option_values.skip_specification) - return usage_error("ERROR: --sector-align not allowed with --skip\n"); - if(0 != option_values.until_specification) - return usage_error("ERROR: --sector-align not allowed with --until\n"); - if(0 != option_values.cue_specification) - return usage_error("ERROR: --sector-align not allowed with --cue\n"); - if(option_values.format_channels >= 0 && option_values.format_channels != 2) - return usage_error("ERROR: --sector-align can only be done with stereo input\n"); - if(option_values.format_bps >= 0 && option_values.format_bps != 16) - return usage_error("ERROR: --sector-align can only be done with 16-bit samples\n"); - if(option_values.format_sample_rate >= 0 && option_values.format_sample_rate != 44100) - return usage_error("ERROR: --sector-align can only be done with a sample rate of 44100\n"); - } if(option_values.replay_gain) { if(option_values.force_to_stdout) return usage_error("ERROR: --replay-gain not allowed with -c/--stdout\n"); @@ -505,7 +480,7 @@ int do_it(void) flac__utils_printf(stderr, 2, "\n"); flac__utils_printf(stderr, 2, "flac %s\n", FLAC__VERSION_STRING); - flac__utils_printf(stderr, 2, "Copyright (C) 2000-2009 Josh Coalson, 2011-2022 Xiph.Org Foundation\n"); + flac__utils_printf(stderr, 2, "Copyright (C) 2000-2009 Josh Coalson, 2011-2023 Xiph.Org Foundation\n"); flac__utils_printf(stderr, 2, "flac comes with ABSOLUTELY NO WARRANTY. This is free software, and you are\n"); flac__utils_printf(stderr, 2, "welcome to redistribute it under certain conditions. Type `flac' for details.\n\n"); @@ -543,8 +518,10 @@ int do_it(void) for(i = 0, retval = 0; i < option_values.num_files; i++) { if(0 == strcmp(option_values.filenames[i], "-") && !first) continue; - retval |= encode_file(option_values.filenames[i], first, i == (option_values.num_files-1)); - first = false; + if(encode_file(option_values.filenames[i], first, i == (option_values.num_files-1))) + retval = 1; + else + first = false; } if(option_values.replay_gain && retval == 0) { float album_gain, album_peak; @@ -571,6 +548,7 @@ FLAC__bool init_options(void) { option_values.show_help = false; option_values.show_explain = false; + option_values.show_version = false; option_values.mode_decode = false; option_values.verify = false; option_values.treat_warnings_as_errors = false; @@ -602,7 +580,6 @@ FLAC__bool init_options(void) option_values.keep_foreign_metadata_if_present = false; option_values.replay_gain = false; option_values.ignore_chunk_sizes = false; - option_values.sector_align = false; option_values.utf8_convert = true; option_values.cmdline_forced_outfilename = 0; option_values.output_prefix = 0; @@ -821,11 +798,6 @@ int parse_option(int short_option, const char *long_option, const char *option_a else if(0 == strcmp(long_option, "ignore-chunk-sizes")) { option_values.ignore_chunk_sizes = true; } - else if(0 == strcmp(long_option, "sector-align")) { - flac__utils_printf(stderr, 1, "WARNING: --sector-align is DEPRECATED and may not exist in future versions of flac.\n"); - flac__utils_printf(stderr, 1, " shntool provides similar functionality\n"); - option_values.sector_align = true; - } #if FLAC__HAS_OGG else if(0 == strcmp(long_option, "ogg")) { option_values.use_ogg = true; @@ -908,9 +880,6 @@ int parse_option(int short_option, const char *long_option, const char *option_a else if(0 == strcmp(long_option, "no-ignore-chunk-sizes")) { option_values.ignore_chunk_sizes = false; } - else if(0 == strcmp(long_option, "no-sector-align")) { - option_values.sector_align = false; - } else if(0 == strcmp(long_option, "no-utf8-convert")) { option_values.utf8_convert = false; } @@ -1243,7 +1212,7 @@ static void usage_header(void) printf("===============================================================================\n"); printf("flac - Command-line FLAC encoder/decoder version %s\n", FLAC__VERSION_STRING); printf("Copyright (C) 2000-2009 Josh Coalson\n"); - printf("Copyright (C) 2011-2022 Xiph.Org Foundation\n"); + printf("Copyright (C) 2011-2023 Xiph.Org Foundation\n"); printf("\n"); printf("This program is free software; you can redistribute it and/or\n"); printf("modify it under the terms of the GNU General Public License\n"); @@ -1337,7 +1306,6 @@ void show_help(void) printf(" -V, --verify Verify a correct encoding\n"); printf(" --lax Allow encoder to generate non-Subset files\n"); printf(" --ignore-chunk-sizes Ignore data chunk sizes in WAVE/AIFF files\n"); - printf(" --sector-align (DEPRECATED) Align multiple files on sector boundaries\n"); printf(" --replay-gain Calculate ReplayGain & store in FLAC tags\n"); printf(" --cuesheet=FILENAME Import cuesheet and store in CUESHEET block\n"); printf(" --picture=SPECIFICATION Import picture and store in PICTURE block\n"); @@ -1403,7 +1371,6 @@ void show_help(void) printf(" --no-residual-gnuplot\n"); printf(" --no-residual-text\n"); printf(" --no-ignore-chunk-sizes\n"); - printf(" --no-sector-align\n"); printf(" --no-seektable\n"); printf(" --no-silent\n"); printf(" --no-force\n"); @@ -1546,10 +1513,6 @@ void show_explain(void) printf(" --ignore-chunk-sizes Ignore data chunk sizes in WAVE/AIFF files;\n"); printf(" useful when piping data from programs which\n"); printf(" generate bogus data chunk sizes.\n"); - printf(" --sector-align Align encoding of multiple CD format WAVE files\n"); - printf(" on sector boundaries. This option is DEPRECATED\n"); - printf(" and may not exist in future versions of flac.\n"); - printf(" shntool offers similar functionality.\n"); printf(" --replay-gain Calculate ReplayGain values and store them as\n"); printf(" FLAC tags. Title gains/peaks will be computed\n"); printf(" for each file, and an album gain/peak will be\n"); @@ -1770,7 +1733,6 @@ void show_explain(void) printf(" --no-residual-gnuplot\n"); printf(" --no-residual-text\n"); printf(" --no-ignore-chunk-sizes\n"); - printf(" --no-sector-align\n"); printf(" --no-seektable\n"); printf(" --no-silent\n"); printf(" --no-force\n"); @@ -1803,13 +1765,11 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ return 1; } -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if(0 == strcmp(infilename, "-")) { infilesize = (FLAC__off_t)(-1); encode_infile = grabbag__file_get_binary_stdin(); } else -#endif { infilesize = grabbag__file_get_filesize(infilename); if(0 == (encode_infile = flac_fopen(infilename, "rb"))) { @@ -1963,17 +1923,6 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ } } - if(option_values.sector_align && (input_format == FORMAT_FLAC || input_format == FORMAT_OGGFLAC)) { - flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input file is FLAC or Ogg FLAC\n"); - conditional_fclose(encode_infile); - return 1; - } - if(option_values.sector_align && input_format == FORMAT_RAW && infilesize < 0) { - flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input size is unknown\n"); - conditional_fclose(encode_infile); - return 1; - } - if(input_format == FORMAT_RAW) { if(option_values.format_is_big_endian < 0 || option_values.format_is_unsigned_samples < 0 || option_values.format_channels < 0 || option_values.format_bps < 0 || option_values.format_sample_rate < 0) { conditional_fclose(encode_infile); @@ -2035,11 +1984,8 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ encode_options.channel_map_none = option_values.channel_map_none; encode_options.is_first_file = is_first_file; encode_options.is_last_file = is_last_file; - encode_options.align_reservoir = align_reservoir; - encode_options.align_reservoir_samples = &align_reservoir_samples; encode_options.replay_gain = option_values.replay_gain; encode_options.ignore_chunk_sizes = option_values.ignore_chunk_sizes; - encode_options.sector_align = option_values.sector_align; encode_options.vorbis_comment = option_values.vorbis_comment; FLAC__ASSERT(sizeof(encode_options.pictures) >= sizeof(option_values.pictures)); memcpy(encode_options.pictures, option_values.pictures, sizeof(option_values.pictures)); @@ -2362,12 +2308,6 @@ int decode_file(const char *infilename) decode_options.channel_map_none = option_values.channel_map_none; decode_options.format = output_format; -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - /* Can't fuzz from stdin */ - if(0 == strcmp(infilename, "-") || 0 == strcmp(outfilename, "-")) - return 1; -#endif - if(output_format == FORMAT_RAW) { decode_options.format_options.raw.is_big_endian = option_values.format_is_big_endian; decode_options.format_options.raw.is_unsigned_samples = option_values.format_is_unsigned_samples; diff --git a/src/flac/utils.c b/src/flac/utils.c index d236dc8e..446150d4 100644 --- a/src/flac/utils.c +++ b/src/flac/utils.c @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2002-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -56,8 +56,18 @@ static FLAC__bool local__parse_uint64_(const char *s, FLAC__uint64 *value) return false; while('\0' != (c = *s++)) - if(c >= '0' && c <= '9') - ret = ret * 10 + (c - '0'); + if(c >= '0' && c <= '9') { + if(ret > UINT64_MAX / 10) /* check for overflow */ + return false; + else if(ret == UINT64_MAX / 10) { + FLAC__uint64 tmp = ret; + ret = ret * 10 + (c - '0'); + if(ret < tmp) + return false; + } + else + ret = ret * 10 + (c - '0'); + } else return false; @@ -300,6 +310,8 @@ FLAC__bool flac__utils_parse_skip_until_specification(const char *s, utils__Skip if(local__parse_uint64_(s, &val)) { spec->value_is_samples = true; + if(val > INT64_MAX) + return false; spec->value.samples = (FLAC__int64)val; if(is_negative) spec->value.samples = -(spec->value.samples); @@ -318,13 +330,17 @@ FLAC__bool flac__utils_parse_skip_until_specification(const char *s, utils__Skip return true; } -void flac__utils_canonicalize_skip_until_specification(utils__SkipUntilSpecification *spec, uint32_t sample_rate) +FLAC__bool flac__utils_canonicalize_skip_until_specification(utils__SkipUntilSpecification *spec, uint32_t sample_rate) { FLAC__ASSERT(0 != spec); if(!spec->value_is_samples) { - spec->value.samples = (FLAC__int64)(spec->value.seconds * (double)sample_rate); + double samples = spec->value.seconds * (double)sample_rate; + if(samples >= (double)INT64_MAX || samples <= (double)INT64_MIN) + return false; + spec->value.samples = (FLAC__int64)(samples); spec->value_is_samples = true; } + return true; } FLAC__bool flac__utils_parse_cue_specification(const char *s, utils__CueSpecification *spec) diff --git a/src/flac/utils.h b/src/flac/utils.h index 2c1f1536..931b4a6e 100644 --- a/src/flac/utils.h +++ b/src/flac/utils.h @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2002-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -66,7 +66,7 @@ void stats_print_name(int level, const char *name); void stats_print_info(int level, const char *format, ...); FLAC__bool flac__utils_parse_skip_until_specification(const char *s, utils__SkipUntilSpecification *spec); -void flac__utils_canonicalize_skip_until_specification(utils__SkipUntilSpecification *spec, uint32_t sample_rate); +FLAC__bool flac__utils_canonicalize_skip_until_specification(utils__SkipUntilSpecification *spec, uint32_t sample_rate); FLAC__bool flac__utils_parse_cue_specification(const char *s, utils__CueSpecification *spec); void flac__utils_canonicalize_cue_specification(const utils__CueSpecification *cue_spec, const FLAC__StreamMetadata_CueSheet *cuesheet, FLAC__uint64 total_samples, utils__SkipUntilSpecification *skip_spec, utils__SkipUntilSpecification *until_spec); diff --git a/src/flac/version.rc b/src/flac/version.rc new file mode 100644 index 00000000..00842b92 --- /dev/null +++ b/src/flac/version.rc @@ -0,0 +1,38 @@ +#include <winver.h> +#include "config.h" + +#if (defined GIT_COMMIT_HASH && defined GIT_COMMIT_DATE) +# ifdef GIT_COMMIT_TAG +# define VERSIONSTRING GIT_COMMIT_TAG +# else +# define VERSIONSTRING "git-" GIT_COMMIT_HASH +# endif +#else +# define VERSIONSTRING PACKAGE_VERSION +#endif + +#define xstr(s) str(s) +#define str(s) #s + +VS_VERSION_INFO VERSIONINFO +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +FILEFLAGS 0 +FILEOS VOS__WINDOWS32 +FILETYPE VFT_DLL +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "flac command line tool for Windows" + VALUE "ProductName", "Free Lossless Audio Codec" + VALUE "ProductVersion", VERSIONSTRING + VALUE "CompanyName", "Xiph.Org" + VALUE "LegalCopyright", "2000-2009 Josh Coalson, 2011-2023 Xiph.Org Foundation" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/src/flac/vorbiscomment.c b/src/flac/vorbiscomment.c index 434b5202..3941ec24 100644 --- a/src/flac/vorbiscomment.c +++ b/src/flac/vorbiscomment.c @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2002-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/flac/vorbiscomment.h b/src/flac/vorbiscomment.h index 6da6452d..a6dcb164 100644 --- a/src/flac/vorbiscomment.h +++ b/src/flac/vorbiscomment.h @@ -1,6 +1,6 @@ /* flac - Command-line FLAC encoder/decoder * Copyright (C) 2002-2009 Josh Coalson - * Copyright (C) 2011-2022 Xiph.Org Foundation + * Copyright (C) 2011-2023 Xiph.Org Foundation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License |