Image: Fix crash loading corrupted/invalid JPEG files

Backport from: afea18f65e
This commit is contained in:
KamFretoZ 2024-08-22 22:52:50 +07:00 committed by lightningterror
parent fd5a652270
commit 9a50218400
1 changed files with 35 additions and 29 deletions

View File

@ -8,6 +8,7 @@
#include "ScopedGuard.h"
#include "StringUtil.h"
#include <common/FastJmp.h>
#include <jpeglib.h>
#include <png.h>
#include <webp/decode.h>
@ -383,39 +384,40 @@ namespace
struct JPEGErrorHandler
{
jpeg_error_mgr err;
jmp_buf jbuf;
fastjmp_buf jbuf;
JPEGErrorHandler()
{
jpeg_std_error(&err);
err.error_exit = &ErrorExit;
}
static void ErrorExit(j_common_ptr cinfo)
{
JPEGErrorHandler* eh = (JPEGErrorHandler*)cinfo->err;
char msg[JMSG_LENGTH_MAX];
eh->err.format_message(cinfo, msg);
Console.ErrorFmt("libjpeg fatal error: {}", msg);
fastjmp_jmp(&eh->jbuf, 1);
}
};
} // namespace
static bool HandleJPEGError(JPEGErrorHandler* eh)
{
jpeg_std_error(&eh->err);
eh->err.error_exit = [](j_common_ptr cinfo) {
JPEGErrorHandler* eh = (JPEGErrorHandler*)cinfo->err;
char msg[JMSG_LENGTH_MAX];
eh->err.format_message(cinfo, msg);
Console.ErrorFmt("libjpeg fatal error: {}", msg);
longjmp(eh->jbuf, 1);
};
if (setjmp(eh->jbuf) == 0)
return true;
return false;
}
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);
@ -541,13 +543,17 @@ 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);