Image: Fix crash loading corrupted/invalid JPEG files

This commit is contained in:
Stenzek 2024-07-14 00:00:45 +10:00
parent b7da118f96
commit afea18f65e
No known key found for this signature in database

View file

@ -5,6 +5,7 @@
#include "common/bitutils.h"
#include "common/byte_stream.h"
#include "common/fastjmp.h"
#include "common/file_system.h"
#include "common/log.h"
#include "common/path.h"
@ -425,39 +426,41 @@ namespace {
struct JPEGErrorHandler
{
jpeg_error_mgr err;
jmp_buf jbuf;
};
} // namespace
fastjmp_buf jbuf;
static bool HandleJPEGError(JPEGErrorHandler* eh)
{
jpeg_std_error(&eh->err);
JPEGErrorHandler()
{
jpeg_std_error(&err);
err.error_exit = &ErrorExit;
}
eh->err.error_exit = [](j_common_ptr cinfo) {
static void ErrorExit(j_common_ptr cinfo)
{
JPEGErrorHandler* eh = (JPEGErrorHandler*)cinfo->err;
char msg[JMSG_LENGTH_MAX];
eh->err.format_message(cinfo, msg);
ERROR_LOG("libjpeg fatal error: {}", msg);
longjmp(eh->jbuf, 1);
};
if (setjmp(eh->jbuf) == 0)
return true;
return false;
}
fastjmp_jmp(&eh->jbuf, 1);
}
};
} // namespace
template<typename T>
static bool WrapJPEGDecompress(RGBA8Image* image, T setup_func)
{
std::vector<u8> scanline;
jpeg_decompress_struct info = {};
JPEGErrorHandler err;
if (!HandleJPEGError(&err))
// NOTE: Be **very** careful not to allocate memory after calling this function.
// It won't get freed, because fastjmp does not unwind the stack.
JPEGErrorHandler errhandler;
if (fastjmp_set(&errhandler.jbuf) != 0)
{
jpeg_destroy_decompress(&info);
return false;
}
jpeg_decompress_struct info;
info.err = &err.err;
info.err = &errhandler.err;
jpeg_create_decompress(&info);
setup_func(info);
@ -584,13 +587,18 @@ template<typename T>
static bool WrapJPEGCompress(const RGBA8Image& image, u8 quality, T setup_func)
{
std::vector<u8> scanline;
jpeg_compress_struct info = {};
JPEGErrorHandler err;
if (!HandleJPEGError(&err))
// NOTE: Be **very** careful not to allocate memory after calling this function.
// It won't get freed, because fastjmp does not unwind the stack.
JPEGErrorHandler errhandler;
if (fastjmp_set(&errhandler.jbuf) != 0)
{
jpeg_destroy_compress(&info);
return false;
}
jpeg_compress_struct info;
info.err = &err.err;
info.err = &errhandler.err;
jpeg_create_compress(&info);
setup_func(info);