Fix overflow of streaminfo total samples (github issue 237)

When writing a FLAC file with over 2^36 samples, the total samples
entry in streaminfo will overflow and wrap around. Setting it to 0
(which means unknown number of samples) makes sure the decoder
doesn't rely on this number

Co-authored-by: Ralph Giles <giles@thaumas.net>
This commit is contained in:
Martijn van Beurden 2022-04-19 17:45:22 +02:00 committed by GitHub
parent 7406eabe17
commit 7385dac383
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 4 deletions

View File

@ -2754,7 +2754,7 @@ void update_metadata_(const FLAC__StreamEncoder *encoder)
{
FLAC__byte b[flac_max(6u, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)];
const FLAC__StreamMetadata *metadata = &encoder->private_->streaminfo;
const FLAC__uint64 samples = metadata->data.stream_info.total_samples;
FLAC__uint64 samples = metadata->data.stream_info.total_samples;
const uint32_t min_framesize = metadata->data.stream_info.min_framesize;
const uint32_t max_framesize = metadata->data.stream_info.max_framesize;
const uint32_t bps = metadata->data.stream_info.bits_per_sample;
@ -2811,6 +2811,8 @@ void update_metadata_(const FLAC__StreamEncoder *encoder)
FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN
- 4
) / 8;
if(samples > (FLAC__U64L(1) << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN))
samples = 0;
b[0] = ((FLAC__byte)(bps-1) << 4) | (FLAC__byte)((samples >> 32) & 0x0F);
b[1] = (FLAC__byte)((samples >> 24) & 0xFF);

View File

@ -96,9 +96,13 @@ FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__
FLAC__ASSERT(metadata->data.stream_info.bits_per_sample <= (1u << FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN));
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.bits_per_sample-1, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN))
return false;
FLAC__ASSERT(metadata->data.stream_info.total_samples < (FLAC__U64L(1) << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN));
if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN))
return false;
if(metadata->data.stream_info.total_samples >= (FLAC__U64L(1) << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)){
if(!FLAC__bitwriter_write_raw_uint64(bw, 0, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN))
return false;
}else{
if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN))
return false;
}
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.stream_info.md5sum, 16))
return false;
break;

View File

@ -1249,6 +1249,29 @@ flac2flac input-SCVA.flac case04e "--no-padding -S 5x"
# case 04f: on file with SEEKTABLE block and size-changing option specified, drop existing SEEKTABLE, new SEEKTABLE with default points
#(already covered by case03c)
test_total_samples_overflow ()
{
total_samples=$1
expected_stored_total_samples=$2
echo $ECHO_N "total_samples overflow test (samples=$total_samples) encode... " $ECHO_C
head -c $total_samples /dev/zero | run_flac --force --verify --sign=signed --sample-rate=96000 -b 16384 --channels=1 --endian=little --bps=8 -o big-$total_samples.flac - || die "ERROR"
echo $ECHO_N "decode... " $ECHO_C
run_flac -t big-$total_samples.flac || die "ERROR"
echo $ECHO_N "check... " $ECHO_C
run_metaflac --show-total-samples big-$total_samples.flac > big-$total_samples.cmp1
echo $expected_stored_total_samples > big-$total_samples.cmp2
diff -q -w big-$total_samples.cmp1 big-$total_samples.cmp2 || die "ERROR"
echo "OK"
rm -f big-$total_samples.flac big-$total_samples.cmp1 big-$total_samples.cmp2
}
if [ "$FLAC__TEST_LEVEL" -gt 1 ] ; then
test_total_samples_overflow 68719476735 68719476735
test_total_samples_overflow 68719476736 0
test_total_samples_overflow 68719476737 0
fi
rm -f out.flac out.meta out1.meta
#@@@ when metaflac handles ogg flac, duplicate flac2flac tests here