From 52d0f7cc5e5206f7d12fda6881314b150c2004cc Mon Sep 17 00:00:00 2001 From: Ryan Francesconi <2917795+ryanfrancesconi@users.noreply.github.com> Date: Sat, 31 Oct 2026 23:40:57 -0700 Subject: [PATCH] FileRef: Rewind the stream before detecting the type by content (#1487) A parser tried for the file extension may leave the stream anywhere, and Matroska::File::read() starts at the current position, so a Matroska file under an extension whose parser rejects it gave a null FileRef. --- taglib/fileref.cpp | 4 ++++ tests/test_fileref.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/taglib/fileref.cpp b/taglib/fileref.cpp index e9b0d58a..a18d6329 100644 --- a/taglib/fileref.cpp +++ b/taglib/fileref.cpp @@ -579,7 +579,9 @@ void FileRef::parse(FileName fileName, bool readAudioProperties, return; // At last, try to resolve file types based on the actual content. + // A parser tried for the extension may have left the stream anywhere. + d->stream->seek(0); d->file = detectByContent(d->stream, readAudioProperties, audioPropertiesStyle); if(d->file) return; @@ -612,7 +614,9 @@ void FileRef::parse(IOStream *stream, bool readAudioProperties, return; // At last, try to resolve file types based on the actual content of the file. + // A parser tried for the extension may have left the stream anywhere. + stream->seek(0); d->file = detectByContent(stream, readAudioProperties, audioPropertiesStyle); } diff --git a/tests/test_fileref.cpp b/tests/test_fileref.cpp index 34adfd78..b82e6b2d 100644 --- a/tests/test_fileref.cpp +++ b/tests/test_fileref.cpp @@ -60,6 +60,9 @@ #ifdef TAGLIB_WITH_MOD #include "xmfile.h" #endif +#ifdef TAGLIB_WITH_MATROSKA +#include "matroskafile.h" +#endif #ifdef TAGLIB_WITH_DSF #include "dsffile.h" #include "dsdifffile.h" @@ -141,6 +144,9 @@ class TestFileRef : public CppUnit::TestFixture #ifdef TAGLIB_WITH_DSF CPPUNIT_TEST(testDSF); CPPUNIT_TEST(testDSDIFF); +#endif +#ifdef TAGLIB_WITH_MATROSKA + CPPUNIT_TEST(testMatroskaWithOtherExtension); #endif CPPUNIT_TEST_SUITE_END(); @@ -403,6 +409,31 @@ public: } #endif +#ifdef TAGLIB_WITH_MATROSKA + void testMatroskaWithOtherExtension() + { + // The parsers for these extensions reject Matroska, so the file is found + // by content detection after a failed parse. + for(const char *ext : { ".flac", ".m4a" }) { + ScopedFileCopy copy("no-tags", ".mka"); + const string newname = copy.fileName() + ext; + CPPUNIT_ASSERT_EQUAL(0, std::rename(copy.fileName().c_str(), newname.c_str())); + { + FileRef f(newname.c_str()); + CPPUNIT_ASSERT(dynamic_cast(f.file())); + CPPUNIT_ASSERT(!f.isNull()); + } + { + FileStream s(newname.c_str()); + FileRef f(&s); + CPPUNIT_ASSERT(dynamic_cast(f.file())); + CPPUNIT_ASSERT(!f.isNull()); + } + deleteFile(newname); + } + } +#endif + void testUnsupported() { FileRef f1(TEST_FILE_PATH_C("no-extension"));