From 8b408749a1efb7a9dba5bed6fec8a2af1023589c Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Sat, 2 Jun 2018 17:23:57 +0200 Subject: [PATCH] Fix crash when importing ID3v2 APIC frames with unexpected type --- src/track/trackmetadatataglib.cpp | 49 ++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/track/trackmetadatataglib.cpp b/src/track/trackmetadatataglib.cpp index 2615ae5bb6..ebbf120946 100644 --- a/src/track/trackmetadatataglib.cpp +++ b/src/track/trackmetadatataglib.cpp @@ -876,6 +876,23 @@ QImage importCoverImageFromVorbisCommentPictureList( return QImage(); } +template +const T* downcastID3v2Frame(TagLib::ID3v2::Frame* frame) { + DEBUG_ASSERT(frame); + // We need to use a safe dynamic_cast at runtime instead of an unsafe + // static_cast at compile time to detect unexpected frame subtypes! + // See also: https://bugs.launchpad.net/mixxx/+bug/1774790 + const T* downcastFrame = dynamic_cast(frame); + VERIFY_OR_DEBUG_ASSERT(downcastFrame) { + // This should only happen when reading corrupt or malformed files + kLogger.warning() + << "Unexpected ID3v2" + << frame->frameID().data() + << "frame type"; + } + return downcastFrame; +} + void importCoverImageFromID3v2Tag(QImage* pCoverArt, const TagLib::ID3v2::Tag& tag) { if (!pCoverArt) { return; // nothing to do @@ -891,10 +908,9 @@ void importCoverImageFromID3v2Tag(QImage* pCoverArt, const TagLib::ID3v2::Tag& t const TagLib::ID3v2::FrameList pFrames = iterAPIC->second; for (const auto coverArtType: kPreferredID3v2PictureTypes) { for (const auto pFrame: pFrames) { - const TagLib::ID3v2::AttachedPictureFrame* pApicFrame = - static_cast(pFrame); - DEBUG_ASSERT(pApicFrame); // trust TagLib - if (pApicFrame->type() == coverArtType) { + const auto* pApicFrame = + downcastID3v2Frame(pFrame); + if (pApicFrame && (pApicFrame->type() == coverArtType)) { QImage image(loadImageFromID3v2PictureFrame(*pApicFrame)); if (image.isNull()) { kLogger.warning() @@ -911,18 +927,19 @@ void importCoverImageFromID3v2Tag(QImage* pCoverArt, const TagLib::ID3v2::Tag& t // Fallback: No best match -> Simply select the 1st loadable image for (const auto pFrame: pFrames) { - const TagLib::ID3v2::AttachedPictureFrame* pApicFrame = - static_cast(pFrame); - DEBUG_ASSERT(pApicFrame); // trust TagLib - const QImage image(loadImageFromID3v2PictureFrame(*pApicFrame)); - if (image.isNull()) { - kLogger.warning() - << "Failed to load image from ID3v2 APIC frame of type" - << pApicFrame->type(); - continue; - } else { - *pCoverArt = image; - return; // success + const auto* pApicFrame = + downcastID3v2Frame(pFrame); + if (pApicFrame) { + const QImage image(loadImageFromID3v2PictureFrame(*pApicFrame)); + if (image.isNull()) { + kLogger.warning() + << "Failed to load image from ID3v2 APIC frame of type" + << pApicFrame->type(); + continue; + } else { + *pCoverArt = image; + return; // success + } } } }