From cfde8798019b063a0c89e095873fa8fc71e3a200 Mon Sep 17 00:00:00 2001 From: cutealien Date: Sun, 8 May 2022 14:42:59 +0000 Subject: [PATCH] Add checks for sane image sizes in some image loaders (bmp, jpg, tga, png) Thanks @sfan5 for the original patch (got modified a bit): https://github.com/minetest/irrlicht/commit/dbd39120e7ed8c0c97e48e2df62347627f3c1d42 Forum: https://irrlicht.sourceforge.io/forum/viewtopic.php?f=2&t=52819&p=306518 Those are the common formats, but rest of image loaders should also call this some day. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6387 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 2 ++ source/Irrlicht/CImageLoaderBMP.cpp | 9 ++++++++- source/Irrlicht/CImageLoaderJPG.cpp | 6 ++++-- source/Irrlicht/CImageLoaderPNG.cpp | 3 +++ source/Irrlicht/CImageLoaderTGA.cpp | 6 ++++++ 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/changes.txt b/changes.txt index 294bcd6c..c52b5915 100644 --- a/changes.txt +++ b/changes.txt @@ -1,6 +1,8 @@ -------------------------- Changes in 1.9 (not yet released) +- Add checks for sane image sizes in some image loaders (so far: bmp, jpg, tga, png). + Thanks @sfan5 for the original patch (got modified a bit): https://github.com/minetest/irrlicht/commit/dbd39120e7ed8c0c97e48e2df62347627f3c1d42 - Add IImage::checkDataSizeLimit and make IImage getDataSizeFromFormat return size_t so image loaders can check if sizes are sane. - 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). diff --git a/source/Irrlicht/CImageLoaderBMP.cpp b/source/Irrlicht/CImageLoaderBMP.cpp index 675212b1..4bb27af5 100644 --- a/source/Irrlicht/CImageLoaderBMP.cpp +++ b/source/Irrlicht/CImageLoaderBMP.cpp @@ -313,6 +313,13 @@ IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const dim.Height = header.Height; IImage* image = 0; + + if ( !IImage::checkDataSizeLimit( (size_t)header.Width*header.Height*header.BPP) ) + { + os::Printer::log("Image dimensions too large for file", file->getFileName(), ELL_WARNING); + goto cleanup; + } + switch(header.BPP) { case 1: @@ -348,7 +355,7 @@ IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const }; // clean up - +cleanup: delete [] paletteData; delete [] bmpData; diff --git a/source/Irrlicht/CImageLoaderJPG.cpp b/source/Irrlicht/CImageLoaderJPG.cpp index af807ab2..0cd6a353 100644 --- a/source/Irrlicht/CImageLoaderJPG.cpp +++ b/source/Irrlicht/CImageLoaderJPG.cpp @@ -232,9 +232,11 @@ IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const u32 width = cinfo.image_width; u32 height = cinfo.image_height; - if ( width > JPEG_MAX_DIMENSION || height > JPEG_MAX_DIMENSION ) + if ( width > JPEG_MAX_DIMENSION || height > JPEG_MAX_DIMENSION + || !IImage::checkDataSizeLimit(IImage::getDataSizeFromFormat(ECF_R8G8B8, width, height)) + ) { - os::Printer::log("Image dimensions too large for JPG in file", filename, ELL_WARNING); + os::Printer::log("Image dimensions too large in file", filename, ELL_ERROR); longjmp(jerr.setjmp_buffer, 1); } diff --git a/source/Irrlicht/CImageLoaderPNG.cpp b/source/Irrlicht/CImageLoaderPNG.cpp index 1df1eada..08fc7201 100644 --- a/source/Irrlicht/CImageLoaderPNG.cpp +++ b/source/Irrlicht/CImageLoaderPNG.cpp @@ -158,6 +158,9 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const Height=h; } + if (!IImage::checkDataSizeLimit((size_t)Width* Height * (BitDepth/8))) + png_cpexcept_error(png_ptr, "Image dimensions too large"); + // Convert palette color to true color if (ColorType==PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); diff --git a/source/Irrlicht/CImageLoaderTGA.cpp b/source/Irrlicht/CImageLoaderTGA.cpp index c9b3a9d5..667f40d6 100644 --- a/source/Irrlicht/CImageLoaderTGA.cpp +++ b/source/Irrlicht/CImageLoaderTGA.cpp @@ -106,6 +106,12 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const header.ImageHeight = os::Byteswap::byteswap(header.ImageHeight); #endif + if (!IImage::checkDataSizeLimit((size_t)header.ImageWidth* header.ImageHeight * (header.PixelDepth/8))) + { + os::Printer::log("Image dimensions too large in file.", file->getFileName(), ELL_ERROR); + return 0; + } + // skip image identification field if (header.IdLength) file->seek(header.IdLength, true);