mirror of
https://github.com/claunia/flac.git
synced 2025-12-16 18:54:26 +00:00
src/encode.c : Fix potential infinite loop in flac-toflac encoding.
A malformed file (generated by AFL) had a 'samples_left_to_process' value of greater than the actual numbe of samples. When re-encoding the decoder would get to the end of the file and then continuously return a decode status of FLAC__STREAM_DECODER_END_OF_STREAM, causing an infinite loop. Solution is to break out of the loop on two consecutive end-of-stream events.
This commit is contained in:
@@ -1050,6 +1050,7 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena
|
|||||||
FLAC__uint64 total_samples_in_input; /* WATCHOUT: may be 0 to mean "unknown" */
|
FLAC__uint64 total_samples_in_input; /* WATCHOUT: may be 0 to mean "unknown" */
|
||||||
FLAC__uint64 skip;
|
FLAC__uint64 skip;
|
||||||
FLAC__uint64 until; /* a value of 0 mean end-of-stream (i.e. --until=-0) */
|
FLAC__uint64 until; /* a value of 0 mean end-of-stream (i.e. --until=-0) */
|
||||||
|
unsigned consecutive_eos_count = 0;
|
||||||
unsigned align_remainder = 0;
|
unsigned align_remainder = 0;
|
||||||
|
|
||||||
switch(options.format) {
|
switch(options.format) {
|
||||||
@@ -1428,13 +1429,25 @@ int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilena
|
|||||||
break;
|
break;
|
||||||
case FORMAT_FLAC:
|
case FORMAT_FLAC:
|
||||||
case FORMAT_OGGFLAC:
|
case FORMAT_OGGFLAC:
|
||||||
|
consecutive_eos_count = 0;
|
||||||
while(!encoder_session.fmt.flac.client_data.fatal_error && encoder_session.fmt.flac.client_data.samples_left_to_process > 0) {
|
while(!encoder_session.fmt.flac.client_data.fatal_error && encoder_session.fmt.flac.client_data.samples_left_to_process > 0) {
|
||||||
|
FLAC__StreamDecoderState decoder_state;
|
||||||
/* We can also hit the end of stream without samples_left_to_process
|
/* We can also hit the end of stream without samples_left_to_process
|
||||||
* going to 0 if there are errors and continue_through_decode_errors
|
* going to 0 if there are errors and continue_through_decode_errors
|
||||||
* is on, so we want to break in that case too:
|
* is on, so we want to break in that case too:
|
||||||
*/
|
*/
|
||||||
if(encoder_session.continue_through_decode_errors && FLAC__stream_decoder_get_state(encoder_session.fmt.flac.decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
|
decoder_state = FLAC__stream_decoder_get_state(encoder_session.fmt.flac.decoder);
|
||||||
|
if(encoder_session.continue_through_decode_errors && decoder_state == FLAC__STREAM_DECODER_END_OF_STREAM)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
consecutive_eos_count = decoder_state == FLAC__STREAM_DECODER_END_OF_STREAM ? consecutive_eos_count + 1 : 0;
|
||||||
|
|
||||||
|
/* Exit loop if we get two or more consecutive FLAC__STREAM_DECODER_END_OF_STREAM events. */
|
||||||
|
if(consecutive_eos_count >= 2) {
|
||||||
|
flac__utils_printf(stderr, 1, "%s: ERROR: %d consecutive FLAC__STREAM_DECODER_END_OF_STREAM events.\n", encoder_session.inbasefilename, consecutive_eos_count);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(!FLAC__stream_decoder_process_single(encoder_session.fmt.flac.decoder)) {
|
if(!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));
|
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);
|
return EncoderSession_finish_error(&encoder_session);
|
||||||
|
|||||||
Reference in New Issue
Block a user