ReadOther in ui/image/image_prepare.cpp (function ReadOther, currently line 458):
const auto size = reader.size();
if (size.width() * size.height() > kReadMaxArea) {
return {};
}
QSize::width() and QSize::height() return int, so size.width() * size.height() is evaluated in int. kReadMaxArea is 12032 * 9024. QImageReader::size() returns the dimensions declared in the file header before decoding, so a crafted file can declare very large dimensions.
For a header that declares 65536 x 65536 the int product is 0, the check passes, and reader.read(&result.image) proceeds to allocate a QImage for the declared size (a 65536x65536 ARGB image is 16 GiB). Other dimensions whose product wraps below kReadMaxArea (for example 65535 x 65535, or 32768 x 65536 which wraps negative) pass the same way. JPEG and WebP are affected too, since QImageReader::size() reports header dimensions for them as well.
Minimal repro. This 68-byte PNG declares 65536 x 65536 in IHDR:
import struct, zlib
def chunk(t, d):
return struct.pack(">I", len(d)) + t + d + struct.pack(">I", zlib.crc32(t + d))
open("overflow.png", "wb").write(
b"\x89PNG\r\n\x1a\n"
+ chunk(b"IHDR", struct.pack(">II", 65536, 65536) + bytes([8, 2, 0, 0, 0]))
+ chunk(b"IDAT", zlib.compress(b"\x00" * 16))
+ chunk(b"IEND", b""))
QImageReader on this file returns size() == 65536x65536; int(65536 * 65536) is 0; the guard passes.
Suggested fix, reject non-positive dimensions and widen the multiplication to qint64:
const auto size = reader.size();
- if (size.width() * size.height() > kReadMaxArea) {
+ if (size.width() <= 0 || size.height() <= 0) {
+ return {};
+ }
+ if (qint64(size.width()) * size.height() > kReadMaxArea) {
return {};
}
ReadOtherinui/image/image_prepare.cpp(functionReadOther, currently line 458):QSize::width()andQSize::height()returnint, sosize.width() * size.height()is evaluated inint.kReadMaxAreais12032 * 9024.QImageReader::size()returns the dimensions declared in the file header before decoding, so a crafted file can declare very large dimensions.For a header that declares
65536 x 65536theintproduct is0, the check passes, andreader.read(&result.image)proceeds to allocate a QImage for the declared size (a 65536x65536 ARGB image is 16 GiB). Other dimensions whose product wraps belowkReadMaxArea(for example65535 x 65535, or32768 x 65536which wraps negative) pass the same way. JPEG and WebP are affected too, sinceQImageReader::size()reports header dimensions for them as well.Minimal repro. This 68-byte PNG declares
65536 x 65536in IHDR:QImageReaderon this file returnssize() == 65536x65536;int(65536 * 65536)is0; the guard passes.Suggested fix, reject non-positive dimensions and widen the multiplication to
qint64: