Fix crash with large jpg files.

Based somewhat on a patch in Minetest from sfan5 594de99153
There might be more problems which may be the reason they checked for other values in Minetest, but don't have more info for now and so far this works.
Forum: https://irrlicht.sourceforge.io/forum/viewtopic.php?f=2&t=52819&p=306518

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6385 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
cutealien 2022-05-06 16:00:26 +00:00
parent 156463da4f
commit 76d013d9d6
2 changed files with 17 additions and 5 deletions

@ -1,6 +1,7 @@
-------------------------- --------------------------
Changes in 1.9 (not yet released) Changes in 1.9 (not yet released)
- Fix crash with large jpg files. Based somewhat on a patch in Minetest from sfan5 https://github.com/minetest/irrlicht/commit/594de9915346a87f67cd94e28c7933993efb5d3b
- COSOperator::getSystemMemory now returns some value on OSX (thought same for total and available). - COSOperator::getSystemMemory now returns some value on OSX (thought same for total and available).
Thanks @sfan5 for patch https://irrlicht.sourceforge.io/forum/viewtopic.php?f=2&t=52819 and https://github.com/minetest/irrlicht/commit/e469c54f76f6d24f92389b4e8a27b9cce7152888 Thanks @sfan5 for patch https://irrlicht.sourceforge.io/forum/viewtopic.php?f=2&t=52819 and https://github.com/minetest/irrlicht/commit/e469c54f76f6d24f92389b4e8a27b9cce7152888
- Fix CVertexBuffer::setType switching types for non-empty arrays. Before we had some bad casts which could result in random initializing of some vertex data. - Fix CVertexBuffer::setType switching types for non-empty arrays. Before we had some bad casts which could result in random initializing of some vertex data.

@ -145,10 +145,13 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
return 0; return 0;
core::stringc filename = file->getFileName(); core::stringc filename = file->getFileName();
long fileSize = file->getSize();
if ( fileSize < 3 )
return 0;
u8 **rowPtr=0; u8 **rowPtr=0;
u8* input = new u8[file->getSize()]; u8* input = new u8[fileSize];
file->read(input, file->getSize()); file->read(input, fileSize);
// allocate and initialize JPEG decompression object // allocate and initialize JPEG decompression object
struct jpeg_decompress_struct cinfo; struct jpeg_decompress_struct cinfo;
@ -188,7 +191,7 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
jpeg_source_mgr jsrc; jpeg_source_mgr jsrc;
// Set up data pointer // Set up data pointer
jsrc.bytes_in_buffer = file->getSize(); jsrc.bytes_in_buffer = fileSize;
jsrc.next_input_byte = (JOCTET*)input; jsrc.next_input_byte = (JOCTET*)input;
cinfo.src = &jsrc; cinfo.src = &jsrc;
@ -225,10 +228,17 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
jpeg_start_decompress(&cinfo); jpeg_start_decompress(&cinfo);
// Get image data // Get image data
u16 rowspan = cinfo.image_width * cinfo.out_color_components; u32 rowspan = cinfo.image_width * cinfo.out_color_components;
u32 width = cinfo.image_width; u32 width = cinfo.image_width;
u32 height = cinfo.image_height; u32 height = cinfo.image_height;
if ( width > JPEG_MAX_DIMENSION || height > JPEG_MAX_DIMENSION )
{
os::Printer::log("Image dimensions too large for JPG in file", filename, ELL_WARNING);
longjmp(jerr.setjmp_buffer, 1);
}
// Allocate memory for buffer // Allocate memory for buffer
u8* output = new u8[rowspan * height]; u8* output = new u8[rowspan * height];
@ -237,7 +247,7 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
// Create array of row pointers for lib // Create array of row pointers for lib
rowPtr = new u8* [height]; rowPtr = new u8* [height];
for( u32 i = 0; i < height; i++ ) for( size_t i = 0; i < height; i++ )
rowPtr[i] = &output[ i * rowspan ]; rowPtr[i] = &output[ i * rowspan ];
u32 rowsRead = 0; u32 rowsRead = 0;
@ -246,6 +256,7 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
rowsRead += jpeg_read_scanlines( &cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead ); rowsRead += jpeg_read_scanlines( &cinfo, &rowPtr[rowsRead], cinfo.output_height - rowsRead );
delete [] rowPtr; delete [] rowPtr;
rowPtr = 0;
// Finish decompression // Finish decompression
jpeg_finish_decompress(&cinfo); jpeg_finish_decompress(&cinfo);