diff --git a/autotests/read/jxl/bug_496350.jxl b/autotests/read/jxl/bug_496350.jxl new file mode 100644 index 0000000..97cb3b9 Binary files /dev/null and b/autotests/read/jxl/bug_496350.jxl differ diff --git a/autotests/read/jxl/bug_496350.png b/autotests/read/jxl/bug_496350.png new file mode 100644 index 0000000..bab81da Binary files /dev/null and b/autotests/read/jxl/bug_496350.png differ diff --git a/src/imageformats/jxl.cpp b/src/imageformats/jxl.cpp index 78243ab..ca09b9b 100644 --- a/src/imageformats/jxl.cpp +++ b/src/imageformats/jxl.cpp @@ -382,6 +382,11 @@ bool QJpegXLHandler::countALLFrames() case JXL_DEC_NEED_MORE_INPUT: qWarning("ERROR: JXL data incomplete"); break; + case JXL_DEC_BOX: + if (!decodeBox(status)) { + qWarning("ERROR: JXL BOX decoding failed"); + } + continue; default: qWarning("Unexpected event %d instead of JXL_DEC_FRAME", status); break; @@ -1214,16 +1219,8 @@ bool QJpegXLHandler::decodeBoxes(JxlDecoderStatus &status) { do { // decode metadata status = JxlDecoderProcessInput(m_decoder); - if (status == JXL_DEC_BOX) { - JxlBoxType type; - JxlDecoderGetBoxType(m_decoder, type, JXL_FALSE); - if (memcmp(type, "xml ", 4) == 0) { - uint64_t size; - if (JxlDecoderGetBoxSizeRaw(m_decoder, &size) == JXL_DEC_SUCCESS && size < uint64_t(kMaxQVectorSize)) { - m_xmp = QByteArray(size, '\0'); - JxlDecoderSetBoxBuffer(m_decoder, reinterpret_cast(m_xmp.data()), m_xmp.size()); - } - } + if (!decodeBox(status)) { + qWarning("ERROR: JXL BOX decoding failed"); } } while (status == JXL_DEC_BOX); @@ -1240,6 +1237,27 @@ bool QJpegXLHandler::decodeBoxes(JxlDecoderStatus &status) return true; } +bool QJpegXLHandler::decodeBox(const JxlDecoderStatus &status) +{ + if (status != JXL_DEC_BOX) { + return true; + } + + JxlBoxType type; + JxlDecoderGetBoxType(m_decoder, type, JXL_FALSE); + if (memcmp(type, "xml ", 4) == 0) { + uint64_t size; + if (JxlDecoderGetBoxSizeRaw(m_decoder, &size) == JXL_DEC_SUCCESS && size < uint64_t(kMaxQVectorSize)) { + m_xmp = QByteArray(size, '\0'); + JxlDecoderSetBoxBuffer(m_decoder, reinterpret_cast(m_xmp.data()), m_xmp.size()); + return true; + } + return false; + } + + return true; +} + QImageIOPlugin::Capabilities QJpegXLPlugin::capabilities(QIODevice *device, const QByteArray &format) const { if (format == "jxl") { diff --git a/src/imageformats/jxl_p.h b/src/imageformats/jxl_p.h index 7648e0c..04aee93 100644 --- a/src/imageformats/jxl_p.h +++ b/src/imageformats/jxl_p.h @@ -52,6 +52,7 @@ private: bool decode_one_frame(); bool rewind(); bool decodeBoxes(JxlDecoderStatus &status); + bool decodeBox(const JxlDecoderStatus &status); enum ParseJpegXLState { ParseJpegXLError = -1,