1010
1111#include " ../lib/TinyEXIF/TinyEXIF.h"
1212
13+ #include < csetjmp>
1314#include < iostream>
1415#include < kodi/Filesystem.h>
1516
17+ namespace
18+ {
19+
20+ // libjpeg's default error_exit calls exit(), and libmpo installs it via
21+ // jpeg_std_error() without overriding it, so a malformed file terminates Kodi
22+ // rather than failing the decode. mpo_decompress_error_exit() can only replace
23+ // the function pointer, not attach state to it, so the jump target is
24+ // thread-local; each decoder instance is driven from one thread at a time.
25+ thread_local std::jmp_buf s_jpegEscape;
26+
27+ void MpoFatalError (j_common_ptr cinfo)
28+ {
29+ char message[JMSG_LENGTH_MAX ] = {};
30+ (*cinfo->err ->format_message )(cinfo, message);
31+ kodi::Log (ADDON_LOG_ERROR , " libjpeg: %s" , message);
32+ std::longjmp (s_jpegEscape, 1 );
33+ }
34+
35+ } // namespace
36+
1637MPOPicture::MPOPicture (const kodi::addon::IInstanceInfo& instance)
1738 : CInstanceImageDecoder(instance)
1839{
@@ -36,8 +57,15 @@ bool MPOPicture::SupportsFile(const std::string& file)
3657
3758 mpo_decompress_struct mpoinfo;
3859 mpo_create_decompress (&mpoinfo);
60+ mpo_decompress_error_exit (&mpoinfo, MpoFatalError);
61+ if (setjmp (s_jpegEscape))
62+ {
63+ mpo_destroy_decompress (&mpoinfo);
64+ return false ;
65+ }
66+
3967 mpo_mem_src (&mpoinfo, buffer.data (), buffer.size ());
40- bool ret = mpo_read_header (&mpoinfo);
68+ const bool ret = mpo_read_header (&mpoinfo);
4169 mpo_destroy_decompress (&mpoinfo);
4270 return ret;
4371}
@@ -139,6 +167,13 @@ bool MPOPicture::LoadImageFromMemory(const std::string& mimetype,
139167 m_data.resize (bufSize);
140168 std::copy (buffer, buffer + bufSize, m_data.begin ());
141169 mpo_create_decompress (&m_mpoinfo);
170+ mpo_decompress_error_exit (&m_mpoinfo, MpoFatalError);
171+ if (setjmp (s_jpegEscape))
172+ {
173+ mpo_destroy_decompress (&m_mpoinfo);
174+ return false ;
175+ }
176+
142177 mpo_mem_src (&m_mpoinfo, m_data.data (), m_data.size ());
143178 if (!mpo_read_header (&m_mpoinfo))
144179 {
@@ -169,6 +204,9 @@ bool MPOPicture::Decode(uint8_t* pixels,
169204 return false ;
170205 }
171206
207+ if (setjmp (s_jpegEscape))
208+ return false ;
209+
172210 size_t image = 0 ;
173211 while (image < m_images)
174212 {
0 commit comments