From 818c5f7627f8fd71750ff09d7dc126ea82e2df8b Mon Sep 17 00:00:00 2001 From: Erik de Castro Lopo Date: Sun, 16 Apr 2017 10:44:28 +1000 Subject: [PATCH] RF64: Fix an RF64_AUTO_DOWNGRADE bug Also add a test for this. The test is disabled by default because it needs to write a 4 Gig file. Change-Id: If9a18f4f6147e08cfa6f7f35ff66131434f0db20 Closes: https://github.com/erikd/libsndfile/issues/238 --- src/rf64.c | 7 ++++++- tests/misc_test.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/rf64.c b/src/rf64.c index a42d474..02dd904 100644 --- a/src/rf64.c +++ b/src/rf64.c @@ -339,6 +339,11 @@ rf64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) } ; break ; + case PAD_MARKER : + psf_log_printf (psf, "%M : %d\n", marker, chunk_size) ; + psf_binheader_readf (psf, "j", chunk_size) ; + break ; + default : if (chunk_size >= 0xffff0000) { psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D with length %u. Exiting parser.\n", marker, psf_ftell (psf) - 8, chunk_size) ; @@ -659,7 +664,7 @@ rf64_write_header (SF_PRIVATE *psf, int calc_length) if (wpriv->rf64_downgrade && psf->filelength < RIFF_DOWNGRADE_BYTES) { psf_binheader_writef (psf, "etm8m", RIFF_MARKER, (psf->filelength < 8) ? 8 : psf->filelength - 8, WAVE_MARKER) ; - psf_binheader_writef (psf, "m4884", JUNK_MARKER, 20, 0, 0, 0, 0) ; + psf_binheader_writef (psf, "m4z", JUNK_MARKER, 24, 24) ; add_fact_chunk = 1 ; } else diff --git a/tests/misc_test.c b/tests/misc_test.c index 90a9d01..7352ada 100644 --- a/tests/misc_test.c +++ b/tests/misc_test.c @@ -1,5 +1,5 @@ /* -** Copyright (C) 2001-2016 Erik de Castro Lopo +** Copyright (C) 2001-2017 Erik de Castro Lopo ** ** This program is free software ; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -52,6 +52,7 @@ static void filesystem_full_test (int format) ; static void permission_test (const char *filename, int typemajor) ; static void wavex_amb_test (const char *filename) ; static void rf64_downgrade_test (const char *filename) ; +static void rf64_long_file_downgrade_test (const char *filename) ; int main (int argc, char *argv []) @@ -145,6 +146,9 @@ main (int argc, char *argv []) filesystem_full_test (SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ; permission_test ("readonly.rf64", SF_FORMAT_RF64) ; rf64_downgrade_test ("downgrade.wav") ; + /* Disable this by default, because it needs to write 4 gigabytes of data. */ + if (SF_FALSE) + rf64_long_file_downgrade_test ("no-downgrade.rf64") ; test_count++ ; } ; @@ -471,3 +475,52 @@ rf64_downgrade_test (const char *filename) return ; } /* rf64_downgrade_test */ + +static void +rf64_long_file_downgrade_test (const char *filename) +{ static int output [BUFFER_LEN] ; + + SNDFILE *file ; + SF_INFO sfinfo ; + sf_count_t k, output_frames = 0 ; + + print_test_name (__func__, filename) ; + + sf_info_clear (&sfinfo) ; + + for (k = 0 ; k < BUFFER_LEN ; k++) + output [k] = 0x1020304 ; + + sfinfo.samplerate = 44100 ; + sfinfo.frames = ARRAY_LEN (output) ; + sfinfo.channels = 1 ; + sfinfo.format = SF_FORMAT_RF64 | SF_FORMAT_PCM_32 ; + + file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; + + exit_if_true (sf_command (file, SFC_RF64_AUTO_DOWNGRADE, NULL, SF_TRUE) != SF_TRUE, "\n\nLine %d: sf_command failed.\n", __LINE__) ; + + while (output_frames * sizeof (output [0]) < 0x100000000) + { test_write_int_or_die (file, 0, output, ARRAY_LEN (output), __LINE__) ; + output_frames += ARRAY_LEN (output) ; + } ; + + sf_close (file) ; + + sf_info_clear (&sfinfo) ; + + file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; + + exit_if_true (sfinfo.format != (SF_FORMAT_RF64 | SF_FORMAT_PCM_32), "\n\nLine %d: RF64 to WAV downgrade should have failed.\n", __LINE__) ; + exit_if_true (sfinfo.channels != 1, "\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ; + exit_if_true (sfinfo.frames != output_frames, "\n\nLine %d: Incorrect number of frames in file (%d should be %d).\n", __LINE__, (int) sfinfo.frames, (int) output_frames) ; + + check_log_buffer_or_die (file, __LINE__) ; + + sf_close (file) ; + + puts ("ok") ; + unlink (filename) ; + + return ; +} /* rf64_long_file_downgrade_test */ -- 2.7.4