From 490a634473d0acb17c840116178cc192f2d6c87f Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 26 Jan 2020 11:54:49 +1100 Subject: [PATCH] oiiodecoder: fixed segfault caused by some OIIO decoders if they received unexpected data When "probing" footage, Olive runs it past all of its decoders until one responds that it can decode this file. However this caused issues when some OIIO decoders would erroneously pick up incompatible files, try to read them and segfault the entire app (notable OpenJPEG with MPEG-4 and RLA with WAVE audio). We now use the file extension to check with OIIO if it "should" be compatible before actually testing if it is. This is not a "perfect" solution (i.e. someone could recreate the segfault by renaming an MPEG-4 file to an image extension like .JPG), but is probably as much as can be done Olive-side and should filter out all segfaults under normal circumstances. --- app/codec/oiio/oiiodecoder.cpp | 19 +++++++++++++++++++ app/codec/oiio/oiiodecoder.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/app/codec/oiio/oiiodecoder.cpp b/app/codec/oiio/oiiodecoder.cpp index c01e20e4a..5ef8b4636 100644 --- a/app/codec/oiio/oiiodecoder.cpp +++ b/app/codec/oiio/oiiodecoder.cpp @@ -21,9 +21,12 @@ #include "oiiodecoder.h" #include +#include #include "common/define.h" +QStringList OIIODecoder::supported_formats_; + OIIODecoder::OIIODecoder() : image_(nullptr), frame_(nullptr) @@ -37,6 +40,22 @@ QString OIIODecoder::id() bool OIIODecoder::Probe(Footage *f) { + // We prioritize OIIO over FFmpeg to pick up still images more effectively, but some OIIO decoders (notably OpenJPEG) + // will segfault entirely if given unexpected data (an MPEG-4 for instance). To workaround this issue, we use OIIO's + // "extension_list" attribute and match it with the extension of the file. + + // Check if we've created the supported formats list, create it if not + if (supported_formats_.isEmpty()) { + supported_formats_ = QString::fromStdString(OIIO::get_string_attribute("extension_list")).split(';'); + } + + // + QFileInfo file_info(f->filename()); + + if (!supported_formats_.contains(file_info.completeSuffix())) { + return false; + } + std::string std_filename = f->filename().toStdString(); auto in = OIIO::ImageInput::open(std_filename); diff --git a/app/codec/oiio/oiiodecoder.h b/app/codec/oiio/oiiodecoder.h index 3d392071f..f4977c40f 100644 --- a/app/codec/oiio/oiiodecoder.h +++ b/app/codec/oiio/oiiodecoder.h @@ -64,6 +64,8 @@ private: FramePtr frame_; + static QStringList supported_formats_; + }; #endif // OIIODECODER_H