diff --git a/src/MPOPicture.cpp b/src/MPOPicture.cpp index 31755a0..21dd72b 100644 --- a/src/MPOPicture.cpp +++ b/src/MPOPicture.cpp @@ -154,17 +154,43 @@ bool MPOPicture::LoadImageFromMemory(const std::string& mimetype, } bool MPOPicture::Decode(uint8_t* pixels, + size_t pixelBufferSize, unsigned int width, unsigned int height, unsigned int pitch, ADDON_IMG_FMT format) { + // The copy loop below writes B,G,R and only fills the fourth byte for + // A8R8G8B8, so that is the only format implemented here. + if (format != ADDON_IMG_FMT_A8R8G8B8) + { + kodi::Log(ADDON_LOG_ERROR, "%s: Unsupported target format (%d)", __func__, + static_cast(format)); + return false; + } + size_t image = 0; while (image < m_images) { mpo_start_decompress(&m_mpoinfo); JSAMPARRAY buffer; int row_stride = m_mpoinfo.cinfo.cinfo.output_width * m_mpoinfo.cinfo.cinfo.output_components; + + // Mirrors the destination offset in the loop below exactly - the integer + // division must be applied in the same order or an odd m_width + // underestimates the reach for images after the first. + const size_t tileOffset = image * m_width / 2 * 4; + if (m_height == 0 || row_stride <= 0 || + static_cast(m_height - 1) * pitch + tileOffset + + static_cast(row_stride / 3) * 4 > + pixelBufferSize) + { + kodi::Log(ADDON_LOG_ERROR, "%s: Output buffer too small for image %zu of %ux%u at pitch %u", + __func__, image, m_width, m_height, pitch); + mpo_finish_decompress(&m_mpoinfo); + return false; + } + size_t lines = 0; while (lines < m_height) { diff --git a/src/MPOPicture.h b/src/MPOPicture.h index b32cce3..b4a4116 100644 --- a/src/MPOPicture.h +++ b/src/MPOPicture.h @@ -28,6 +28,7 @@ class ATTR_DLL_LOCAL MPOPicture : public kodi::addon::CInstanceImageDecoder unsigned int& width, unsigned int& height) override; bool Decode(uint8_t* pixels, + size_t pixelBufferSize, unsigned int width, unsigned int height, unsigned int pitch,